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 -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # Keep Primitive-type-ids in sync if you add types here.
  424   # 0x40
  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   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431 
  432 Primitive-type-ids:  # (addr int)
  433   0x40
  434 
  435 # == Type definitions
  436 # Program->types contains some typeinfo for each type definition.
  437 # Types contain vars with types, but can't specify registers.
  438 Typeinfo-id:  # type-id
  439   0/imm32
  440 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  441   4/imm32
  442 # Total size must be >= 0
  443 # During parsing it may take on two additional values:
  444 #   -2: not yet initialized
  445 #   -1: in process of being computed
  446 # See populate-mu-type-sizes for details.
  447 Typeinfo-total-size-in-bytes:  # int
  448   0xc/imm32
  449 Typeinfo-next:  # (handle typeinfo)
  450   0x10/imm32
  451 Typeinfo-size:  # (addr int)
  452   0x18/imm32
  453 
  454 # Each entry in the typeinfo->fields table has a pointer to a string and a
  455 # pointer to a typeinfo-entry.
  456 Typeinfo-fields-row-size:  # (addr int)
  457   0x10/imm32
  458 
  459 # typeinfo-entry objects have information about a field in a single record type
  460 #
  461 # each field of a type is represented using two var's:
  462 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  463 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  464 # computing the output happens after parsing; in the meantime we preserve the
  465 # order of fields in the 'index' field.
  466 Typeinfo-entry-input-var:  # (handle var)
  467   0/imm32
  468 Typeinfo-entry-index:  # int
  469   8/imm32
  470 Typeinfo-entry-output-var:  # (handle var)
  471   0xc/imm32
  472 Typeinfo-entry-size:  # (addr int)
  473   0x14/imm32
  474 
  475 == code
  476 
  477 Entry:
  478     # . prologue
  479     89/<- %ebp 4/r32/esp
  480     (new-segment *Heap-size Heap)
  481     # if (argv[1] == "test') run-tests()
  482     {
  483       # if (argc <= 1) break
  484       81 7/subop/compare *ebp 1/imm32
  485       7e/jump-if-<= break/disp8
  486       # if (argv[1] != "test") break
  487       (kernel-string-equal? *(ebp+8) "test")  # => eax
  488       3d/compare-eax-and 0/imm32/false
  489       74/jump-if-= break/disp8
  490       #
  491       (run-tests)
  492       # syscall(exit, *Num-test-failures)
  493       8b/-> *Num-test-failures 3/r32/ebx
  494       eb/jump $mu-main:end/disp8
  495     }
  496     # otherwise convert Stdin
  497     (convert-mu Stdin Stdout Stderr 0)
  498     (flush Stdout)
  499     # syscall(exit, 0)
  500     bb/copy-to-ebx 0/imm32
  501 $mu-main:end:
  502     e8/call syscall_exit/disp32
  503 
  504 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  505     # . prologue
  506     55/push-ebp
  507     89/<- %ebp 4/r32/esp
  508     # . save registers
  509     50/push-eax
  510     # initialize global data structures
  511     c7 0/subop/copy *Next-block-index 1/imm32
  512     8b/-> *Primitive-type-ids 0/r32/eax
  513     89/<- *Type-id 0/r32/eax  # stream-write
  514     c7 0/subop/copy *_Program-functions 0/imm32
  515     c7 0/subop/copy *_Program-functions->payload 0/imm32
  516     c7 0/subop/copy *_Program-types 0/imm32
  517     c7 0/subop/copy *_Program-types->payload 0/imm32
  518     c7 0/subop/copy *_Program-signatures 0/imm32
  519     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  520     #
  521     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  522     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  523 #?     (dump-typeinfos "=== typeinfos\n")
  524     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  525     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  526 $convert-mu:end:
  527     # . restore registers
  528     58/pop-to-eax
  529     # . epilogue
  530     89/<- %esp 5/r32/ebp
  531     5d/pop-to-ebp
  532     c3/return
  533 
  534 test-convert-empty-input:
  535     # empty input => empty output
  536     # . prologue
  537     55/push-ebp
  538     89/<- %ebp 4/r32/esp
  539     # setup
  540     (clear-stream _test-input-stream)
  541     (clear-stream $_test-input-buffered-file->buffer)
  542     (clear-stream _test-output-stream)
  543     (clear-stream $_test-output-buffered-file->buffer)
  544     #
  545     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  546     (flush _test-output-buffered-file)
  547     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  548     # . epilogue
  549     89/<- %esp 5/r32/ebp
  550     5d/pop-to-ebp
  551     c3/return
  552 
  553 test-convert-function-skeleton:
  554     # . prologue
  555     55/push-ebp
  556     89/<- %ebp 4/r32/esp
  557     # setup
  558     (clear-stream _test-input-stream)
  559     (clear-stream $_test-input-buffered-file->buffer)
  560     (clear-stream _test-output-stream)
  561     (clear-stream $_test-output-buffered-file->buffer)
  562     #
  563     (write _test-input-stream "fn foo {\n")
  564     (write _test-input-stream "}\n")
  565     # convert
  566     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  567     (flush _test-output-buffered-file)
  568 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  574     # check output
  575     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  576     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  577     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  578     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  579     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  580     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  581     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  582     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  583     # . epilogue
  584     89/<- %esp 5/r32/ebp
  585     5d/pop-to-ebp
  586     c3/return
  587 
  588 test-convert-multiple-function-skeletons:
  589     # . prologue
  590     55/push-ebp
  591     89/<- %ebp 4/r32/esp
  592     # setup
  593     (clear-stream _test-input-stream)
  594     (clear-stream $_test-input-buffered-file->buffer)
  595     (clear-stream _test-output-stream)
  596     (clear-stream $_test-output-buffered-file->buffer)
  597     #
  598     (write _test-input-stream "fn foo {\n")
  599     (write _test-input-stream "}\n")
  600     (write _test-input-stream "fn bar {\n")
  601     (write _test-input-stream "}\n")
  602     # convert
  603     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  604     (flush _test-output-buffered-file)
  605 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  611     # check first function
  612     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  613     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  614     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  615     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  616     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  617     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  618     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  619     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  620     # check second function
  621     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  622     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  623     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  624     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  625     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  626     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  627     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  628     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  629     # . epilogue
  630     89/<- %esp 5/r32/ebp
  631     5d/pop-to-ebp
  632     c3/return
  633 
  634 test-convert-function-with-arg:
  635     # . prologue
  636     55/push-ebp
  637     89/<- %ebp 4/r32/esp
  638     # setup
  639     (clear-stream _test-input-stream)
  640     (clear-stream $_test-input-buffered-file->buffer)
  641     (clear-stream _test-output-stream)
  642     (clear-stream $_test-output-buffered-file->buffer)
  643     #
  644     (write _test-input-stream "fn foo n: int {\n")
  645     (write _test-input-stream "}\n")
  646     # convert
  647     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  648     (flush _test-output-buffered-file)
  649 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  655     # check output
  656     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  657     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  658     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  659     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  660     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  661     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  662     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  663     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  664     # . epilogue
  665     89/<- %esp 5/r32/ebp
  666     5d/pop-to-ebp
  667     c3/return
  668 
  669 test-function-with-inout-in-register:
  670     # . prologue
  671     55/push-ebp
  672     89/<- %ebp 4/r32/esp
  673     # setup
  674     (clear-stream _test-input-stream)
  675     (clear-stream $_test-input-buffered-file->buffer)
  676     (clear-stream _test-output-stream)
  677     (clear-stream $_test-output-buffered-file->buffer)
  678     (clear-stream _test-error-stream)
  679     (clear-stream $_test-error-buffered-file->buffer)
  680     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  681     68/push 0/imm32
  682     68/push 0/imm32
  683     89/<- %edx 4/r32/esp
  684     (tailor-exit-descriptor %edx 0x10)
  685     #
  686     (write _test-input-stream "fn foo x/eax: int {\n")
  687     (write _test-input-stream "}\n")
  688     # convert
  689     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  690     # registers except esp clobbered at this point
  691     # restore ed
  692     89/<- %edx 4/r32/esp
  693     (flush _test-output-buffered-file)
  694     (flush _test-error-buffered-file)
  695 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  701     # check output
  702     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  703     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  704     # check that stop(1) was called
  705     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  706     # don't restore from ebp
  707     81 0/subop/add %esp 8/imm32
  708     # . epilogue
  709     5d/pop-to-ebp
  710     c3/return
  711 
  712 test-convert-function-with-arg-and-body:
  713     # . prologue
  714     55/push-ebp
  715     89/<- %ebp 4/r32/esp
  716     # setup
  717     (clear-stream _test-input-stream)
  718     (clear-stream $_test-input-buffered-file->buffer)
  719     (clear-stream _test-output-stream)
  720     (clear-stream $_test-output-buffered-file->buffer)
  721     #
  722     (write _test-input-stream "fn foo n: int {\n")
  723     (write _test-input-stream "  increment n\n")
  724     (write _test-input-stream "}\n")
  725     # convert
  726     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  727     (flush _test-output-buffered-file)
  728 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  734     # check output
  735     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
  736     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
  737     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
  738     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
  739     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
  740     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
  741     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
  742     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
  743     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
  744     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
  745     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
  746     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
  747     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
  748     # . epilogue
  749     89/<- %esp 5/r32/ebp
  750     5d/pop-to-ebp
  751     c3/return
  752 
  753 test-convert-function-distinguishes-args:
  754     # . prologue
  755     55/push-ebp
  756     89/<- %ebp 4/r32/esp
  757     # setup
  758     (clear-stream _test-input-stream)
  759     (clear-stream $_test-input-buffered-file->buffer)
  760     (clear-stream _test-output-stream)
  761     (clear-stream $_test-output-buffered-file->buffer)
  762     #
  763     (write _test-input-stream "fn foo a: int, b: int {\n")
  764     (write _test-input-stream "  increment b\n")
  765     (write _test-input-stream "}\n")
  766     # convert
  767     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  768     (flush _test-output-buffered-file)
  769 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  775     # check output
  776     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
  777     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
  778     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
  779     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
  780     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
  781     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
  782     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
  783     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
  784     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
  785     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
  786     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
  787     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
  788     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
  789     # . epilogue
  790     89/<- %esp 5/r32/ebp
  791     5d/pop-to-ebp
  792     c3/return
  793 
  794 test-convert-function-with-return-literal:
  795     # . prologue
  796     55/push-ebp
  797     89/<- %ebp 4/r32/esp
  798     # setup
  799     (clear-stream _test-input-stream)
  800     (clear-stream $_test-input-buffered-file->buffer)
  801     (clear-stream _test-output-stream)
  802     (clear-stream $_test-output-buffered-file->buffer)
  803     #
  804     (write _test-input-stream "fn foo -> _/eax: int {\n")
  805     (write _test-input-stream "  return 0\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-return-literal/0")
  818     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
  819     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
  820     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
  821     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
  822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
  823     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
  824     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
  825     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
  826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
  827     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
  828     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
  829     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
  830     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
  831     # . epilogue
  832     89/<- %esp 5/r32/ebp
  833     5d/pop-to-ebp
  834     c3/return
  835 
  836 test-convert-function-with-return:
  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 -> _/eax: int {\n")
  847     (write _test-input-stream "  var y: int\n")
  848     (write _test-input-stream "  return y\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-return/0")
  861     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
  862     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
  863     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
  864     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
  865     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
  866     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
  867     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
  868     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
  869     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
  870     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
  871     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
  872     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
  873     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
  874     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
  875     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
  876     # . epilogue
  877     89/<- %esp 5/r32/ebp
  878     5d/pop-to-ebp
  879     c3/return
  880 
  881 test-convert-function-with-return-register:
  882     # . prologue
  883     55/push-ebp
  884     89/<- %ebp 4/r32/esp
  885     # setup
  886     (clear-stream _test-input-stream)
  887     (clear-stream $_test-input-buffered-file->buffer)
  888     (clear-stream _test-output-stream)
  889     (clear-stream $_test-output-buffered-file->buffer)
  890     #
  891     (write _test-input-stream "fn foo -> _/eax: int {\n")
  892     (write _test-input-stream "  var y/eax: int <- copy 3\n")
  893     (write _test-input-stream "  return y\n")
  894     (write _test-input-stream "}\n")
  895     # convert
  896     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  897     (flush _test-output-buffered-file)
  898 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  904     # check output
  905     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
  906     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
  907     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
  908     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
  909     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
  910     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
  911     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
  912     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
  913     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
  914     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
  915     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
  916     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
  917     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
  918     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
  919     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
  920     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
  921     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
  922     # . epilogue
  923     89/<- %esp 5/r32/ebp
  924     5d/pop-to-ebp
  925     c3/return
  926 
  927 test-function-with-output-without-register:
  928     # . prologue
  929     55/push-ebp
  930     89/<- %ebp 4/r32/esp
  931     # setup
  932     (clear-stream _test-input-stream)
  933     (clear-stream $_test-input-buffered-file->buffer)
  934     (clear-stream _test-output-stream)
  935     (clear-stream $_test-output-buffered-file->buffer)
  936     (clear-stream _test-error-stream)
  937     (clear-stream $_test-error-buffered-file->buffer)
  938     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  939     68/push 0/imm32
  940     68/push 0/imm32
  941     89/<- %edx 4/r32/esp
  942     (tailor-exit-descriptor %edx 0x10)
  943     #
  944     (write _test-input-stream "fn foo -> _: int {\n")
  945     (write _test-input-stream "}\n")
  946     # convert
  947     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  948     # registers except esp clobbered at this point
  949     # restore ed
  950     89/<- %edx 4/r32/esp
  951     (flush _test-output-buffered-file)
  952     (flush _test-error-buffered-file)
  953 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  959     # check output
  960     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
  961     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
  962     # check that stop(1) was called
  963     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
  964     # don't restore from ebp
  965     81 0/subop/add %esp 8/imm32
  966     # . epilogue
  967     5d/pop-to-ebp
  968     c3/return
  969 
  970 test-function-with-outputs-in-conflicting-registers:
  971     # . prologue
  972     55/push-ebp
  973     89/<- %ebp 4/r32/esp
  974     # setup
  975     (clear-stream _test-input-stream)
  976     (clear-stream $_test-input-buffered-file->buffer)
  977     (clear-stream _test-output-stream)
  978     (clear-stream $_test-output-buffered-file->buffer)
  979     (clear-stream _test-error-stream)
  980     (clear-stream $_test-error-buffered-file->buffer)
  981     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  982     68/push 0/imm32
  983     68/push 0/imm32
  984     89/<- %edx 4/r32/esp
  985     (tailor-exit-descriptor %edx 0x10)
  986     #
  987     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
  988     (write _test-input-stream "}\n")
  989     # convert
  990     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  991     # registers except esp clobbered at this point
  992     # restore ed
  993     89/<- %edx 4/r32/esp
  994     (flush _test-output-buffered-file)
  995     (flush _test-error-buffered-file)
  996 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1002     # check output
 1003     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1004     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1005     # check that stop(1) was called
 1006     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1007     # don't restore from ebp
 1008     81 0/subop/add %esp 8/imm32
 1009     # . epilogue
 1010     5d/pop-to-ebp
 1011     c3/return
 1012 
 1013 test-function-with-named-output:
 1014     # . prologue
 1015     55/push-ebp
 1016     89/<- %ebp 4/r32/esp
 1017     # setup
 1018     (clear-stream _test-input-stream)
 1019     (clear-stream $_test-input-buffered-file->buffer)
 1020     (clear-stream _test-output-stream)
 1021     (clear-stream $_test-output-buffered-file->buffer)
 1022     (clear-stream _test-error-stream)
 1023     (clear-stream $_test-error-buffered-file->buffer)
 1024     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1025     68/push 0/imm32
 1026     68/push 0/imm32
 1027     89/<- %edx 4/r32/esp
 1028     (tailor-exit-descriptor %edx 0x10)
 1029     #
 1030     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1031     (write _test-input-stream "  return 0\n")
 1032     (write _test-input-stream "}\n")
 1033     # convert
 1034     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1035     # registers except esp clobbered at this point
 1036     # restore ed
 1037     89/<- %edx 4/r32/esp
 1038     (flush _test-output-buffered-file)
 1039     (flush _test-error-buffered-file)
 1040 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1046     # check output
 1047     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1048     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1049     # check that stop(1) was called
 1050     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1051     # don't restore from ebp
 1052     81 0/subop/add %esp 8/imm32
 1053     # . epilogue
 1054     5d/pop-to-ebp
 1055     c3/return
 1056 
 1057 test-return-with-wrong-type:
 1058     # . prologue
 1059     55/push-ebp
 1060     89/<- %ebp 4/r32/esp
 1061     # setup
 1062     (clear-stream _test-input-stream)
 1063     (clear-stream $_test-input-buffered-file->buffer)
 1064     (clear-stream _test-output-stream)
 1065     (clear-stream $_test-output-buffered-file->buffer)
 1066     (clear-stream _test-error-stream)
 1067     (clear-stream $_test-error-buffered-file->buffer)
 1068     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1069     68/push 0/imm32
 1070     68/push 0/imm32
 1071     89/<- %edx 4/r32/esp
 1072     (tailor-exit-descriptor %edx 0x10)
 1073     #
 1074     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1075     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1076     (write _test-input-stream "  return x\n")
 1077     (write _test-input-stream "}\n")
 1078     # convert
 1079     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1080     # registers except esp clobbered at this point
 1081     # restore ed
 1082     89/<- %edx 4/r32/esp
 1083     (flush _test-output-buffered-file)
 1084     (flush _test-error-buffered-file)
 1085 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1091     # check output
 1092     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1093     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1094     # check that stop(1) was called
 1095     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1096     # don't restore from ebp
 1097     81 0/subop/add %esp 8/imm32
 1098     # . epilogue
 1099     5d/pop-to-ebp
 1100     c3/return
 1101 
 1102 test-missing-return:
 1103     # . prologue
 1104     55/push-ebp
 1105     89/<- %ebp 4/r32/esp
 1106     # setup
 1107     (clear-stream _test-input-stream)
 1108     (clear-stream $_test-input-buffered-file->buffer)
 1109     (clear-stream _test-output-stream)
 1110     (clear-stream $_test-output-buffered-file->buffer)
 1111     (clear-stream _test-error-stream)
 1112     (clear-stream $_test-error-buffered-file->buffer)
 1113     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1114     68/push 0/imm32
 1115     68/push 0/imm32
 1116     89/<- %edx 4/r32/esp
 1117     (tailor-exit-descriptor %edx 0x10)
 1118     #
 1119     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1120     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1121     (write _test-input-stream "}\n")
 1122     # convert
 1123     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1124     # registers except esp clobbered at this point
 1125     # restore ed
 1126     89/<- %edx 4/r32/esp
 1127     (flush _test-output-buffered-file)
 1128     (flush _test-error-buffered-file)
 1129 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1135     # check output
 1136     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1137     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1138     # check that stop(1) was called
 1139     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1140     # don't restore from ebp
 1141     81 0/subop/add %esp 8/imm32
 1142     # . epilogue
 1143     5d/pop-to-ebp
 1144     c3/return
 1145 
 1146 test-early-exit-without-return:
 1147     # . prologue
 1148     55/push-ebp
 1149     89/<- %ebp 4/r32/esp
 1150     # setup
 1151     (clear-stream _test-input-stream)
 1152     (clear-stream $_test-input-buffered-file->buffer)
 1153     (clear-stream _test-output-stream)
 1154     (clear-stream $_test-output-buffered-file->buffer)
 1155     (clear-stream _test-error-stream)
 1156     (clear-stream $_test-error-buffered-file->buffer)
 1157     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1158     68/push 0/imm32
 1159     68/push 0/imm32
 1160     89/<- %edx 4/r32/esp
 1161     (tailor-exit-descriptor %edx 0x10)
 1162     #
 1163     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1164     (write _test-input-stream "  break\n")
 1165     (write _test-input-stream "  return 0\n")
 1166     (write _test-input-stream "}\n")
 1167     # convert
 1168     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1169     # registers except esp clobbered at this point
 1170     # restore ed
 1171     89/<- %edx 4/r32/esp
 1172     (flush _test-output-buffered-file)
 1173     (flush _test-error-buffered-file)
 1174 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1180     # check output
 1181     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1182     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1183     # check that stop(1) was called
 1184     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1185     # don't restore from ebp
 1186     81 0/subop/add %esp 8/imm32
 1187     # . epilogue
 1188     5d/pop-to-ebp
 1189     c3/return
 1190 
 1191 test-return-with-too-few-inouts:
 1192     # . prologue
 1193     55/push-ebp
 1194     89/<- %ebp 4/r32/esp
 1195     # setup
 1196     (clear-stream _test-input-stream)
 1197     (clear-stream $_test-input-buffered-file->buffer)
 1198     (clear-stream _test-output-stream)
 1199     (clear-stream $_test-output-buffered-file->buffer)
 1200     (clear-stream _test-error-stream)
 1201     (clear-stream $_test-error-buffered-file->buffer)
 1202     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1203     68/push 0/imm32
 1204     68/push 0/imm32
 1205     89/<- %edx 4/r32/esp
 1206     (tailor-exit-descriptor %edx 0x10)
 1207     #
 1208     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1209     (write _test-input-stream "  return\n")
 1210     (write _test-input-stream "}\n")
 1211     # convert
 1212     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1213     # registers except esp clobbered at this point
 1214     # restore ed
 1215     89/<- %edx 4/r32/esp
 1216     (flush _test-output-buffered-file)
 1217     (flush _test-error-buffered-file)
 1218 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1224     # check output
 1225     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1226     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1227     # check that stop(1) was called
 1228     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1229     # don't restore from ebp
 1230     81 0/subop/add %esp 8/imm32
 1231     # . epilogue
 1232     5d/pop-to-ebp
 1233     c3/return
 1234 
 1235 test-return-with-too-many-inouts:
 1236     # . prologue
 1237     55/push-ebp
 1238     89/<- %ebp 4/r32/esp
 1239     # setup
 1240     (clear-stream _test-input-stream)
 1241     (clear-stream $_test-input-buffered-file->buffer)
 1242     (clear-stream _test-output-stream)
 1243     (clear-stream $_test-output-buffered-file->buffer)
 1244     (clear-stream _test-error-stream)
 1245     (clear-stream $_test-error-buffered-file->buffer)
 1246     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1247     68/push 0/imm32
 1248     68/push 0/imm32
 1249     89/<- %edx 4/r32/esp
 1250     (tailor-exit-descriptor %edx 0x10)
 1251     #
 1252     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1253     (write _test-input-stream "  return 0, 0\n")
 1254     (write _test-input-stream "}\n")
 1255     # convert
 1256     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1257     # registers except esp clobbered at this point
 1258     # restore ed
 1259     89/<- %edx 4/r32/esp
 1260     (flush _test-output-buffered-file)
 1261     (flush _test-error-buffered-file)
 1262 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1268     # check output
 1269     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1270     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1271     # check that stop(1) was called
 1272     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1273     # don't restore from ebp
 1274     81 0/subop/add %esp 8/imm32
 1275     # . epilogue
 1276     5d/pop-to-ebp
 1277     c3/return
 1278 
 1279 test-return-unavailable-value:
 1280     # . prologue
 1281     55/push-ebp
 1282     89/<- %ebp 4/r32/esp
 1283     # setup
 1284     (clear-stream _test-input-stream)
 1285     (clear-stream $_test-input-buffered-file->buffer)
 1286     (clear-stream _test-output-stream)
 1287     (clear-stream $_test-output-buffered-file->buffer)
 1288     (clear-stream _test-error-stream)
 1289     (clear-stream $_test-error-buffered-file->buffer)
 1290     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1291     68/push 0/imm32
 1292     68/push 0/imm32
 1293     89/<- %edx 4/r32/esp
 1294     (tailor-exit-descriptor %edx 0x10)
 1295     #
 1296     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1297     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1298     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1299     (write _test-input-stream "  return y, x\n")
 1300     (write _test-input-stream "}\n")
 1301     # convert
 1302     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1303     # registers except esp clobbered at this point
 1304     # restore ed
 1305     89/<- %edx 4/r32/esp
 1306     (flush _test-output-buffered-file)
 1307     (flush _test-error-buffered-file)
 1308 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1314     # check output
 1315     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1316     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1317     # check that stop(1) was called
 1318     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1319     # don't restore from ebp
 1320     81 0/subop/add %esp 8/imm32
 1321     # . epilogue
 1322     5d/pop-to-ebp
 1323     c3/return
 1324 
 1325 test-convert-return-with-duplicate-values:
 1326     # . prologue
 1327     55/push-ebp
 1328     89/<- %ebp 4/r32/esp
 1329     # setup
 1330     (clear-stream _test-input-stream)
 1331     (clear-stream $_test-input-buffered-file->buffer)
 1332     (clear-stream _test-output-stream)
 1333     (clear-stream $_test-output-buffered-file->buffer)
 1334     #
 1335     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1336     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1337     (write _test-input-stream "  return x, x\n")
 1338     (write _test-input-stream "}\n")
 1339     # convert
 1340     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1341     (flush _test-output-buffered-file)
 1342 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1348     # check output
 1349     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1350     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1351     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1352     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1353     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1354     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1355     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1356     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1357     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1358     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1359     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1360     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1361     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1362     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1363     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1364     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1365     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1366     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1367     # . epilogue
 1368     89/<- %esp 5/r32/ebp
 1369     5d/pop-to-ebp
 1370     c3/return
 1371 
 1372 test-convert-return-with-duplicate-values-2:
 1373     # . prologue
 1374     55/push-ebp
 1375     89/<- %ebp 4/r32/esp
 1376     # setup
 1377     (clear-stream _test-input-stream)
 1378     (clear-stream $_test-input-buffered-file->buffer)
 1379     (clear-stream _test-output-stream)
 1380     (clear-stream $_test-output-buffered-file->buffer)
 1381     #
 1382     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1383     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1384     (write _test-input-stream "  return x, x\n")
 1385     (write _test-input-stream "}\n")
 1386     # convert
 1387     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1388     (flush _test-output-buffered-file)
 1389 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1395     # check output
 1396     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1397     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1398     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1399     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1400     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1401     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1402     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1403     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1404     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1405     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1406     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1407     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1408     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1410     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1411     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1412     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1413     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1414     # . epilogue
 1415     89/<- %esp 5/r32/ebp
 1416     5d/pop-to-ebp
 1417     c3/return
 1418 
 1419 test-convert-function-with-literal-arg:
 1420     # . prologue
 1421     55/push-ebp
 1422     89/<- %ebp 4/r32/esp
 1423     # setup
 1424     (clear-stream _test-input-stream)
 1425     (clear-stream $_test-input-buffered-file->buffer)
 1426     (clear-stream _test-output-stream)
 1427     (clear-stream $_test-output-buffered-file->buffer)
 1428     #
 1429     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 1430     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1431     (write _test-input-stream "  result <- add 1\n")
 1432     (write _test-input-stream "  return result\n")
 1433     (write _test-input-stream "}\n")
 1434     # convert
 1435     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1436     (flush _test-output-buffered-file)
 1437 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1443     # check output
 1444     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 1445     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 1446     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 1447     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 1448     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 1449     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 1450     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 1451     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 1452     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 1453     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 1454     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 1455     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 1456     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 1457     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 1458     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 1459     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 1460     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 1461     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 1462     # . epilogue
 1463     89/<- %esp 5/r32/ebp
 1464     5d/pop-to-ebp
 1465     c3/return
 1466 
 1467 test-convert-function-with-literal-arg-2:
 1468     # . prologue
 1469     55/push-ebp
 1470     89/<- %ebp 4/r32/esp
 1471     # setup
 1472     (clear-stream _test-input-stream)
 1473     (clear-stream $_test-input-buffered-file->buffer)
 1474     (clear-stream _test-output-stream)
 1475     (clear-stream $_test-output-buffered-file->buffer)
 1476     #
 1477     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 1478     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 1479     (write _test-input-stream "  result <- add 1\n")
 1480     (write _test-input-stream "  return result\n")
 1481     (write _test-input-stream "}\n")
 1482     # convert
 1483     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1484     (flush _test-output-buffered-file)
 1485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1491     # check output
 1492     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 1493     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 1494     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 1495     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 1496     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 1497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 1498     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 1499     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 1500     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 1501     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 1502     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 1503     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 1504     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 1505     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 1506     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 1507     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 1508     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 1509     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 1510     # . epilogue
 1511     89/<- %esp 5/r32/ebp
 1512     5d/pop-to-ebp
 1513     c3/return
 1514 
 1515 test-convert-function-call-with-literal-arg:
 1516     # . prologue
 1517     55/push-ebp
 1518     89/<- %ebp 4/r32/esp
 1519     # setup
 1520     (clear-stream _test-input-stream)
 1521     (clear-stream $_test-input-buffered-file->buffer)
 1522     (clear-stream _test-output-stream)
 1523     (clear-stream $_test-output-buffered-file->buffer)
 1524     #
 1525     (write _test-input-stream "fn main -> _/ebx: int {\n")
 1526     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 1527     (write _test-input-stream "  return result\n")
 1528     (write _test-input-stream "}\n")
 1529     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 1530     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1531     (write _test-input-stream "  result <- add b\n")
 1532     (write _test-input-stream "  return result\n")
 1533     (write _test-input-stream "}\n")
 1534     # convert
 1535     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1536     (flush _test-output-buffered-file)
 1537 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1543     # check output
 1544     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 1545     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 1546     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 1547     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 1548     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 1549     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 1550     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 1551     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 1552     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1553     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 1554     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1555     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 1556     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 1557     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 1558     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 1559     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 1560     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 1561     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 1562     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 1563     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 1564     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 1565     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 1566     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 1567     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 1568     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 1569     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 1570     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 1571     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 1572     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 1573     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 1574     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 1575     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 1576     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 1577     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 1578     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 1579     # . epilogue
 1580     89/<- %esp 5/r32/ebp
 1581     5d/pop-to-ebp
 1582     c3/return
 1583 
 1584 test-convert-function-call-with-signature:
 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     #
 1594     (write _test-input-stream "fn main -> _/ebx: int {\n")
 1595     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 1596     (write _test-input-stream "  return result\n")
 1597     (write _test-input-stream "}\n")
 1598     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 1599     # convert
 1600     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1601     (flush _test-output-buffered-file)
 1602 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1608     # check output
 1609     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 1610     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 1611     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 1612     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 1613     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 1614     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 1615     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 1616     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 1617     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1618     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 1619     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1620     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 1621     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 1622     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 1623     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 1624     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 1625     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 1626     # . epilogue
 1627     89/<- %esp 5/r32/ebp
 1628     5d/pop-to-ebp
 1629     c3/return
 1630 
 1631 test-convert-function-with-local-var-in-mem:
 1632     # . prologue
 1633     55/push-ebp
 1634     89/<- %ebp 4/r32/esp
 1635     # setup
 1636     (clear-stream _test-input-stream)
 1637     (clear-stream $_test-input-buffered-file->buffer)
 1638     (clear-stream _test-output-stream)
 1639     (clear-stream $_test-output-buffered-file->buffer)
 1640     #
 1641     (write _test-input-stream "fn foo {\n")
 1642     (write _test-input-stream "  var x: int\n")
 1643     (write _test-input-stream "  increment x\n")
 1644     (write _test-input-stream "}\n")
 1645     # convert
 1646     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1647     (flush _test-output-buffered-file)
 1648 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1654     # check output
 1655     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 1656     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 1657     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 1658     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 1659     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 1660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 1661     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 1662     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 1663     (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")
 1664     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 1665     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 1666     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 1667     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 1668     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 1669     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 1670     # . epilogue
 1671     89/<- %esp 5/r32/ebp
 1672     5d/pop-to-ebp
 1673     c3/return
 1674 
 1675 test-convert-invalid-literal:
 1676     # . prologue
 1677     55/push-ebp
 1678     89/<- %ebp 4/r32/esp
 1679     # setup
 1680     (clear-stream _test-input-stream)
 1681     (clear-stream $_test-input-buffered-file->buffer)
 1682     (clear-stream _test-output-stream)
 1683     (clear-stream $_test-output-buffered-file->buffer)
 1684     (clear-stream _test-error-stream)
 1685     (clear-stream $_test-error-buffered-file->buffer)
 1686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1687     68/push 0/imm32
 1688     68/push 0/imm32
 1689     89/<- %edx 4/r32/esp
 1690     (tailor-exit-descriptor %edx 0x10)
 1691     #
 1692     (write _test-input-stream "fn foo {\n")
 1693     (write _test-input-stream "  increment 1n\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 1710     (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")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-local-var-in-mem-has-no-initializer:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     (clear-stream _test-error-stream)
 1729     (clear-stream $_test-error-buffered-file->buffer)
 1730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1731     68/push 0/imm32
 1732     68/push 0/imm32
 1733     89/<- %edx 4/r32/esp
 1734     (tailor-exit-descriptor %edx 0x10)
 1735     #
 1736     (write _test-input-stream "fn foo {\n")
 1737     (write _test-input-stream "  var x: int <- copy 0\n")
 1738     (write _test-input-stream "  increment x\n")
 1739     (write _test-input-stream "}\n")
 1740     # convert
 1741     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1742     # registers except esp clobbered at this point
 1743     # restore ed
 1744     89/<- %edx 4/r32/esp
 1745     (flush _test-output-buffered-file)
 1746     (flush _test-error-buffered-file)
 1747 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1753     # check output
 1754     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 1755     (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")
 1756     # check that stop(1) was called
 1757     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 1758     # don't restore from ebp
 1759     81 0/subop/add %esp 8/imm32
 1760     # . epilogue
 1761     5d/pop-to-ebp
 1762     c3/return
 1763 
 1764 test-convert-function-with-local-var-with-compound-type-in-mem:
 1765     # . prologue
 1766     55/push-ebp
 1767     89/<- %ebp 4/r32/esp
 1768     # setup
 1769     (clear-stream _test-input-stream)
 1770     (clear-stream $_test-input-buffered-file->buffer)
 1771     (clear-stream _test-output-stream)
 1772     (clear-stream $_test-output-buffered-file->buffer)
 1773     #
 1774     (write _test-input-stream "fn foo {\n")
 1775     (write _test-input-stream "  var x: (addr int)\n")
 1776     (write _test-input-stream "  copy-to x, 0\n")
 1777     (write _test-input-stream "}\n")
 1778     # convert
 1779     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1780     (flush _test-output-buffered-file)
 1781 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1787     # check output
 1788     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 1789     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 1790     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 1791     (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")
 1792     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 1793     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 1794     (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")
 1795     (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")
 1796     (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")
 1797     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 1798     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 1799     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 1800     (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")
 1801     (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")
 1802     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 1803     # . epilogue
 1804     89/<- %esp 5/r32/ebp
 1805     5d/pop-to-ebp
 1806     c3/return
 1807 
 1808 test-convert-function-with-local-var-in-reg:
 1809     # . prologue
 1810     55/push-ebp
 1811     89/<- %ebp 4/r32/esp
 1812     # setup
 1813     (clear-stream _test-input-stream)
 1814     (clear-stream $_test-input-buffered-file->buffer)
 1815     (clear-stream _test-output-stream)
 1816     (clear-stream $_test-output-buffered-file->buffer)
 1817     #
 1818     (write _test-input-stream "fn foo {\n")
 1819     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1820     (write _test-input-stream "  x <- increment\n")
 1821     (write _test-input-stream "}\n")
 1822     # convert
 1823     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1824     (flush _test-output-buffered-file)
 1825 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1831     # check output
 1832     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 1833     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 1834     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 1835     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 1836     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 1837     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 1838     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 1839     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 1840     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 1841     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 1842     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 1843     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 1844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 1845     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 1846     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 1847     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 1848     # . epilogue
 1849     89/<- %esp 5/r32/ebp
 1850     5d/pop-to-ebp
 1851     c3/return
 1852 
 1853 test-convert-function-with-allocate:
 1854     # . prologue
 1855     55/push-ebp
 1856     89/<- %ebp 4/r32/esp
 1857     # setup
 1858     (clear-stream _test-input-stream)
 1859     (clear-stream $_test-input-buffered-file->buffer)
 1860     (clear-stream _test-output-stream)
 1861     (clear-stream $_test-output-buffered-file->buffer)
 1862     #
 1863     (write _test-input-stream "fn foo {\n")
 1864     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 1865     (write _test-input-stream "  allocate x\n")
 1866     (write _test-input-stream "}\n")
 1867     # convert
 1868     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1869     (flush _test-output-buffered-file)
 1870 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1876     # check output
 1877     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 1878     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 1879     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 1880     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 1881     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 1882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 1883     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 1884     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 1885     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 1886     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 1887     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 1888     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 1889     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 1890     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 1891     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 1892     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 1893     # . epilogue
 1894     89/<- %esp 5/r32/ebp
 1895     5d/pop-to-ebp
 1896     c3/return
 1897 
 1898 test-initializer-in-hex:
 1899     # . prologue
 1900     55/push-ebp
 1901     89/<- %ebp 4/r32/esp
 1902     # setup
 1903     (clear-stream _test-input-stream)
 1904     (clear-stream $_test-input-buffered-file->buffer)
 1905     (clear-stream _test-output-stream)
 1906     (clear-stream $_test-output-buffered-file->buffer)
 1907     (clear-stream _test-error-stream)
 1908     (clear-stream $_test-error-buffered-file->buffer)
 1909     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1910     68/push 0/imm32
 1911     68/push 0/imm32
 1912     89/<- %edx 4/r32/esp
 1913     (tailor-exit-descriptor %edx 0x10)
 1914     #
 1915     (write _test-input-stream "fn foo {\n")
 1916     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 1917     (write _test-input-stream "}\n")
 1918     # convert
 1919     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1920     # registers except esp clobbered at this point
 1921     # restore ed
 1922     89/<- %edx 4/r32/esp
 1923     (flush _test-output-buffered-file)
 1924     (flush _test-error-buffered-file)
 1925 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1931     # check output
 1932     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 1933     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-initializer-in-hex: error message")
 1934     # check that stop(1) was called
 1935     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 1936     # don't restore from ebp
 1937     81 0/subop/add %esp 8/imm32
 1938     # . epilogue
 1939     5d/pop-to-ebp
 1940     c3/return
 1941 
 1942 test-convert-function-with-second-local-var-in-same-reg:
 1943     # . prologue
 1944     55/push-ebp
 1945     89/<- %ebp 4/r32/esp
 1946     # setup
 1947     (clear-stream _test-input-stream)
 1948     (clear-stream $_test-input-buffered-file->buffer)
 1949     (clear-stream _test-output-stream)
 1950     (clear-stream $_test-output-buffered-file->buffer)
 1951     #
 1952     (write _test-input-stream "fn foo {\n")
 1953     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1954     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1955     (write _test-input-stream "  y <- increment\n")
 1956     (write _test-input-stream "}\n")
 1957     # convert
 1958     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1959     (flush _test-output-buffered-file)
 1960 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1966     # check output
 1967     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 1968     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 1969     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 1970     (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")
 1971     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 1972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 1973     (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")
 1974     (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")
 1975     (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")
 1976     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 1977     (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")
 1978     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 1979     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 1980     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 1981     (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")
 1982     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 1983     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 1984     # . epilogue
 1985     89/<- %esp 5/r32/ebp
 1986     5d/pop-to-ebp
 1987     c3/return
 1988 
 1989 test-read-clobbered-reg-var:
 1990     # . prologue
 1991     55/push-ebp
 1992     89/<- %ebp 4/r32/esp
 1993     # setup
 1994     (clear-stream _test-input-stream)
 1995     (clear-stream $_test-input-buffered-file->buffer)
 1996     (clear-stream _test-output-stream)
 1997     (clear-stream $_test-output-buffered-file->buffer)
 1998     (clear-stream _test-error-stream)
 1999     (clear-stream $_test-error-buffered-file->buffer)
 2000     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2001     68/push 0/imm32
 2002     68/push 0/imm32
 2003     89/<- %edx 4/r32/esp
 2004     (tailor-exit-descriptor %edx 0x10)
 2005     #
 2006     (write _test-input-stream "fn foo {\n")
 2007     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2008     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2009     (write _test-input-stream "  x <- increment\n")
 2010     (write _test-input-stream "}\n")
 2011     # convert
 2012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2013     # registers except esp clobbered at this point
 2014     # restore ed
 2015     89/<- %edx 4/r32/esp
 2016     (flush _test-output-buffered-file)
 2017     (flush _test-error-buffered-file)
 2018 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2024     # check output
 2025     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2026     (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")
 2027     # check that stop(1) was called
 2028     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2029     # don't restore from ebp
 2030     81 0/subop/add %esp 8/imm32
 2031     # . epilogue
 2032     5d/pop-to-ebp
 2033     c3/return
 2034 
 2035 test-overlapping-int-fp-registers:
 2036     # . prologue
 2037     55/push-ebp
 2038     89/<- %ebp 4/r32/esp
 2039     # setup
 2040     (clear-stream _test-input-stream)
 2041     (clear-stream $_test-input-buffered-file->buffer)
 2042     (clear-stream _test-output-stream)
 2043     (clear-stream $_test-output-buffered-file->buffer)
 2044     (clear-stream _test-error-stream)
 2045     (clear-stream $_test-error-buffered-file->buffer)
 2046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2047     68/push 0/imm32
 2048     68/push 0/imm32
 2049     89/<- %edx 4/r32/esp
 2050     (tailor-exit-descriptor %edx 0x10)
 2051     #
 2052     (write _test-input-stream "fn foo {\n")
 2053     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2054     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2055     (write _test-input-stream "  x <- increment\n")
 2056     (write _test-input-stream "}\n")
 2057     # convert
 2058     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2059     # registers except esp clobbered at this point
 2060     # restore ed
 2061     89/<- %edx 4/r32/esp
 2062     (flush _test-output-buffered-file)
 2063     (flush _test-error-buffered-file)
 2064 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2070     # no errors
 2071     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2072     # don't bother checking the generated code
 2073     # don't restore from ebp
 2074     81 0/subop/add %esp 8/imm32
 2075     # . epilogue
 2076     5d/pop-to-ebp
 2077     c3/return
 2078 
 2079 test-convert-function-call:
 2080     # . prologue
 2081     55/push-ebp
 2082     89/<- %ebp 4/r32/esp
 2083     # setup
 2084     (clear-stream _test-input-stream)
 2085     (clear-stream $_test-input-buffered-file->buffer)
 2086     (clear-stream _test-output-stream)
 2087     (clear-stream $_test-output-buffered-file->buffer)
 2088     #
 2089     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2090     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2091     (write _test-input-stream "  return result\n")
 2092     (write _test-input-stream "}\n")
 2093     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2094     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2095     (write _test-input-stream "  return result\n")
 2096     (write _test-input-stream "}\n")
 2097     # convert
 2098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2099     (flush _test-output-buffered-file)
 2100 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2106     # check output
 2107     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2108     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2109     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2110     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2111     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2112     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2113     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2114     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2115     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2116     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2117     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2118     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2119     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2120     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2121     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2122     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2123     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2124     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2125     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2126     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2127     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2128     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2129     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2130     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2131     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2132     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2133     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2134     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2135     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2136     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2137     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2138     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2139     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2140     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2141     # . epilogue
 2142     89/<- %esp 5/r32/ebp
 2143     5d/pop-to-ebp
 2144     c3/return
 2145 
 2146 test-convert-function-call-with-inout-with-compound-type:
 2147     # . prologue
 2148     55/push-ebp
 2149     89/<- %ebp 4/r32/esp
 2150     # setup
 2151     (clear-stream _test-input-stream)
 2152     (clear-stream $_test-input-buffered-file->buffer)
 2153     (clear-stream _test-output-stream)
 2154     (clear-stream $_test-output-buffered-file->buffer)
 2155     #
 2156     (write _test-input-stream "fn f {\n")
 2157     (write _test-input-stream "  var x: (addr int)\n")
 2158     (write _test-input-stream "  g x\n")
 2159     (write _test-input-stream "}\n")
 2160     (write _test-input-stream "fn g a: (addr int) {\n")
 2161     (write _test-input-stream "}\n")
 2162     # convert
 2163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2164     (flush _test-output-buffered-file)
 2165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2171     # check output
 2172     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2177     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2178     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2179     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2180     (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")
 2181     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2182     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2183     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2184     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2185     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2186     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2187     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2188     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2189     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2190     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2191     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2192     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2193     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2194     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2195     # . epilogue
 2196     89/<- %esp 5/r32/ebp
 2197     5d/pop-to-ebp
 2198     c3/return
 2199 
 2200 test-convert-function-call-with-inout-with-type-parameter:
 2201     # . prologue
 2202     55/push-ebp
 2203     89/<- %ebp 4/r32/esp
 2204     # setup
 2205     (clear-stream _test-input-stream)
 2206     (clear-stream $_test-input-buffered-file->buffer)
 2207     (clear-stream _test-output-stream)
 2208     (clear-stream $_test-output-buffered-file->buffer)
 2209     (clear-stream _test-error-stream)
 2210     (clear-stream $_test-error-buffered-file->buffer)
 2211     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2212     68/push 0/imm32
 2213     68/push 0/imm32
 2214     89/<- %edx 4/r32/esp
 2215     (tailor-exit-descriptor %edx 0x10)
 2216     #
 2217     (write _test-input-stream "fn f {\n")
 2218     (write _test-input-stream "  var x: (addr int)\n")
 2219     (write _test-input-stream "  g x\n")
 2220     (write _test-input-stream "}\n")
 2221     (write _test-input-stream "fn g a: (addr _) {\n")
 2222     (write _test-input-stream "}\n")
 2223     # convert
 2224     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2225     # registers except esp clobbered at this point
 2226     # restore ed
 2227     89/<- %edx 4/r32/esp
 2228     (flush _test-output-buffered-file)
 2229     (flush _test-error-buffered-file)
 2230 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2236     # no error; types matched
 2237     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 2238     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 2239     # don't restore from ebp
 2240     81 0/subop/add %esp 8/imm32
 2241     # . epilogue
 2242     5d/pop-to-ebp
 2243     c3/return
 2244 
 2245 test-convert-function-call-with-incorrect-inout-type:
 2246     # . prologue
 2247     55/push-ebp
 2248     89/<- %ebp 4/r32/esp
 2249     # setup
 2250     (clear-stream _test-input-stream)
 2251     (clear-stream $_test-input-buffered-file->buffer)
 2252     (clear-stream _test-output-stream)
 2253     (clear-stream $_test-output-buffered-file->buffer)
 2254     (clear-stream _test-error-stream)
 2255     (clear-stream $_test-error-buffered-file->buffer)
 2256     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2257     68/push 0/imm32
 2258     68/push 0/imm32
 2259     89/<- %edx 4/r32/esp
 2260     (tailor-exit-descriptor %edx 0x10)
 2261     #
 2262     (write _test-input-stream "fn f {\n")
 2263     (write _test-input-stream "  var x: int\n")
 2264     (write _test-input-stream "  g x\n")
 2265     (write _test-input-stream "}\n")
 2266     (write _test-input-stream "fn g a: foo {\n")
 2267     (write _test-input-stream "}\n")
 2268     # convert
 2269     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2270     # registers except esp clobbered at this point
 2271     # restore ed
 2272     89/<- %edx 4/r32/esp
 2273     (flush _test-output-buffered-file)
 2274     (flush _test-error-buffered-file)
 2275 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2281     # check output
 2282     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 2283     (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")
 2284     # check that stop(1) was called
 2285     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 2286     # don't restore from ebp
 2287     81 0/subop/add %esp 8/imm32
 2288     5d/pop-to-ebp
 2289     c3/return
 2290 
 2291 test-convert-function-call-with-inout-with-incorrect-compound-type:
 2292     # . prologue
 2293     55/push-ebp
 2294     89/<- %ebp 4/r32/esp
 2295     # setup
 2296     (clear-stream _test-input-stream)
 2297     (clear-stream $_test-input-buffered-file->buffer)
 2298     (clear-stream _test-output-stream)
 2299     (clear-stream $_test-output-buffered-file->buffer)
 2300     (clear-stream _test-error-stream)
 2301     (clear-stream $_test-error-buffered-file->buffer)
 2302     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2303     68/push 0/imm32
 2304     68/push 0/imm32
 2305     89/<- %edx 4/r32/esp
 2306     (tailor-exit-descriptor %edx 0x10)
 2307     #
 2308     (write _test-input-stream "fn f {\n")
 2309     (write _test-input-stream "  var x: (addr int)\n")
 2310     (write _test-input-stream "  g x\n")
 2311     (write _test-input-stream "}\n")
 2312     (write _test-input-stream "fn g a: (addr bool) {\n")
 2313     (write _test-input-stream "}\n")
 2314     # convert
 2315     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2316     # registers except esp clobbered at this point
 2317     # restore ed
 2318     89/<- %edx 4/r32/esp
 2319     (flush _test-output-buffered-file)
 2320     (flush _test-error-buffered-file)
 2321 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2327     # check output
 2328     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 2329     (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")
 2330     # don't restore from ebp
 2331     81 0/subop/add %esp 8/imm32
 2332     # . epilogue
 2333     5d/pop-to-ebp
 2334     c3/return
 2335 
 2336 test-convert-function-call-with-inout-with-multiple-type-parameters:
 2337     # . prologue
 2338     55/push-ebp
 2339     89/<- %ebp 4/r32/esp
 2340     # setup
 2341     (clear-stream _test-input-stream)
 2342     (clear-stream $_test-input-buffered-file->buffer)
 2343     (clear-stream _test-output-stream)
 2344     (clear-stream $_test-output-buffered-file->buffer)
 2345     (clear-stream _test-error-stream)
 2346     (clear-stream $_test-error-buffered-file->buffer)
 2347     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2348     68/push 0/imm32
 2349     68/push 0/imm32
 2350     89/<- %edx 4/r32/esp
 2351     (tailor-exit-descriptor %edx 0x10)
 2352     #
 2353     (write _test-input-stream "fn f {\n")
 2354     (write _test-input-stream "  var x: (addr int)\n")
 2355     (write _test-input-stream "  var y: (addr int)\n")
 2356     (write _test-input-stream "  g x, y\n")
 2357     (write _test-input-stream "}\n")
 2358     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 2359     (write _test-input-stream "}\n")
 2360     # convert
 2361     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2362     # registers except esp clobbered at this point
 2363     # restore ed
 2364     89/<- %edx 4/r32/esp
 2365     (flush _test-output-buffered-file)
 2366     (flush _test-error-buffered-file)
 2367 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2373     # no errors
 2374     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 2375     # don't bother checking the generated code
 2376     # don't restore from ebp
 2377     81 0/subop/add %esp 8/imm32
 2378     # . epilogue
 2379     5d/pop-to-ebp
 2380     c3/return
 2381 
 2382 test-type-parameter-matches-rest-of-type:
 2383     # . prologue
 2384     55/push-ebp
 2385     89/<- %ebp 4/r32/esp
 2386     # setup
 2387     (clear-stream _test-input-stream)
 2388     (clear-stream $_test-input-buffered-file->buffer)
 2389     (clear-stream _test-output-stream)
 2390     (clear-stream $_test-output-buffered-file->buffer)
 2391     (clear-stream _test-error-stream)
 2392     (clear-stream $_test-error-buffered-file->buffer)
 2393     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2394     68/push 0/imm32
 2395     68/push 0/imm32
 2396     89/<- %edx 4/r32/esp
 2397     (tailor-exit-descriptor %edx 0x10)
 2398     #
 2399     (write _test-input-stream "fn f {\n")
 2400     (write _test-input-stream "  var x: (addr array int)\n")
 2401     (write _test-input-stream "  g x\n")
 2402     (write _test-input-stream "}\n")
 2403     (write _test-input-stream "fn g a: (addr _) {\n")
 2404     (write _test-input-stream "}\n")
 2405     # convert
 2406     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2407     # registers except esp clobbered at this point
 2408     # restore ed
 2409     89/<- %edx 4/r32/esp
 2410     (flush _test-output-buffered-file)
 2411     (flush _test-error-buffered-file)
 2412 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2418     # no errors
 2419     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 2420     # don't bother checking the generated code
 2421     # don't restore from ebp
 2422     81 0/subop/add %esp 8/imm32
 2423     # . epilogue
 2424     5d/pop-to-ebp
 2425     c3/return
 2426 
 2427 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 2428     # . prologue
 2429     55/push-ebp
 2430     89/<- %ebp 4/r32/esp
 2431     # setup
 2432     (clear-stream _test-input-stream)
 2433     (clear-stream $_test-input-buffered-file->buffer)
 2434     (clear-stream _test-output-stream)
 2435     (clear-stream $_test-output-buffered-file->buffer)
 2436     (clear-stream _test-error-stream)
 2437     (clear-stream $_test-error-buffered-file->buffer)
 2438     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2439     68/push 0/imm32
 2440     68/push 0/imm32
 2441     89/<- %edx 4/r32/esp
 2442     (tailor-exit-descriptor %edx 0x10)
 2443     #
 2444     (write _test-input-stream "fn f {\n")
 2445     (write _test-input-stream "  var x: (addr int)\n")
 2446     (write _test-input-stream "  var y: (addr boolean)\n")
 2447     (write _test-input-stream "  g x, y\n")
 2448     (write _test-input-stream "}\n")
 2449     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 2450     (write _test-input-stream "}\n")
 2451     # convert
 2452     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2453     # registers except esp clobbered at this point
 2454     # restore ed
 2455     89/<- %edx 4/r32/esp
 2456     (flush _test-output-buffered-file)
 2457     (flush _test-error-buffered-file)
 2458 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2464     # check output
 2465     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 2466     (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")
 2467     # don't restore from ebp
 2468     81 0/subop/add %esp 8/imm32
 2469     # . epilogue
 2470     5d/pop-to-ebp
 2471     c3/return
 2472 
 2473 test-convert-function-call-with-too-few-inouts:
 2474     # . prologue
 2475     55/push-ebp
 2476     89/<- %ebp 4/r32/esp
 2477     # setup
 2478     (clear-stream _test-input-stream)
 2479     (clear-stream $_test-input-buffered-file->buffer)
 2480     (clear-stream _test-output-stream)
 2481     (clear-stream $_test-output-buffered-file->buffer)
 2482     (clear-stream _test-error-stream)
 2483     (clear-stream $_test-error-buffered-file->buffer)
 2484     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2485     68/push 0/imm32
 2486     68/push 0/imm32
 2487     89/<- %edx 4/r32/esp
 2488     (tailor-exit-descriptor %edx 0x10)
 2489     #
 2490     (write _test-input-stream "fn f {\n")
 2491     (write _test-input-stream "  g\n")
 2492     (write _test-input-stream "}\n")
 2493     (write _test-input-stream "fn g a: int {\n")
 2494     (write _test-input-stream "}\n")
 2495     # convert
 2496     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2497     # registers except esp clobbered at this point
 2498     # restore ed
 2499     89/<- %edx 4/r32/esp
 2500     (flush _test-output-buffered-file)
 2501     (flush _test-error-buffered-file)
 2502 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2508     # check output
 2509     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 2510     (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")
 2511     # check that stop(1) was called
 2512     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 2513     # don't restore from ebp
 2514     81 0/subop/add %esp 8/imm32
 2515     5d/pop-to-ebp
 2516     c3/return
 2517 
 2518 test-convert-function-call-with-too-many-inouts:
 2519     # . prologue
 2520     55/push-ebp
 2521     89/<- %ebp 4/r32/esp
 2522     # setup
 2523     (clear-stream _test-input-stream)
 2524     (clear-stream $_test-input-buffered-file->buffer)
 2525     (clear-stream _test-output-stream)
 2526     (clear-stream $_test-output-buffered-file->buffer)
 2527     (clear-stream _test-error-stream)
 2528     (clear-stream $_test-error-buffered-file->buffer)
 2529     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2530     68/push 0/imm32
 2531     68/push 0/imm32
 2532     89/<- %edx 4/r32/esp
 2533     (tailor-exit-descriptor %edx 0x10)
 2534     #
 2535     (write _test-input-stream "fn f {\n")
 2536     (write _test-input-stream "  var x: int\n")
 2537     (write _test-input-stream "  g x\n")
 2538     (write _test-input-stream "}\n")
 2539     (write _test-input-stream "fn g {\n")
 2540     (write _test-input-stream "}\n")
 2541     # convert
 2542     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2543     # registers except esp clobbered at this point
 2544     # restore ed
 2545     89/<- %edx 4/r32/esp
 2546     (flush _test-output-buffered-file)
 2547     (flush _test-error-buffered-file)
 2548 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2554     # check output
 2555     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 2556     (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")
 2557     # check that stop(1) was called
 2558     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 2559     # don't restore from ebp
 2560     81 0/subop/add %esp 8/imm32
 2561     5d/pop-to-ebp
 2562     c3/return
 2563 
 2564 test-convert-function-call-with-incorrect-output-type:
 2565     # . prologue
 2566     55/push-ebp
 2567     89/<- %ebp 4/r32/esp
 2568     # setup
 2569     (clear-stream _test-input-stream)
 2570     (clear-stream $_test-input-buffered-file->buffer)
 2571     (clear-stream _test-output-stream)
 2572     (clear-stream $_test-output-buffered-file->buffer)
 2573     (clear-stream _test-error-stream)
 2574     (clear-stream $_test-error-buffered-file->buffer)
 2575     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2576     68/push 0/imm32
 2577     68/push 0/imm32
 2578     89/<- %edx 4/r32/esp
 2579     (tailor-exit-descriptor %edx 0x10)
 2580     #
 2581     (write _test-input-stream "fn f {\n")
 2582     (write _test-input-stream "  var x/eax: int <- g\n")
 2583     (write _test-input-stream "}\n")
 2584     (write _test-input-stream "fn g -> _/eax: foo {\n")
 2585     (write _test-input-stream "}\n")
 2586     # convert
 2587     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2588     # registers except esp clobbered at this point
 2589     # restore ed
 2590     89/<- %edx 4/r32/esp
 2591     (flush _test-output-buffered-file)
 2592     (flush _test-error-buffered-file)
 2593 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2599     # check output
 2600     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 2601     (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")
 2602     # check that stop(1) was called
 2603     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 2604     # don't restore from ebp
 2605     81 0/subop/add %esp 8/imm32
 2606     5d/pop-to-ebp
 2607     c3/return
 2608 
 2609 test-convert-function-call-with-too-few-outputs:
 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     (clear-stream _test-error-stream)
 2619     (clear-stream $_test-error-buffered-file->buffer)
 2620     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2621     68/push 0/imm32
 2622     68/push 0/imm32
 2623     89/<- %edx 4/r32/esp
 2624     (tailor-exit-descriptor %edx 0x10)
 2625     #
 2626     (write _test-input-stream "fn f {\n")
 2627     (write _test-input-stream "  g\n")
 2628     (write _test-input-stream "}\n")
 2629     (write _test-input-stream "fn g -> _/eax: int {\n")
 2630     (write _test-input-stream "}\n")
 2631     # convert
 2632     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2633     # registers except esp clobbered at this point
 2634     # restore ed
 2635     89/<- %edx 4/r32/esp
 2636     (flush _test-output-buffered-file)
 2637     (flush _test-error-buffered-file)
 2638 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2644     # check output
 2645     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 2646     (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")
 2647     # check that stop(1) was called
 2648     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 2649     # don't restore from ebp
 2650     81 0/subop/add %esp 8/imm32
 2651     5d/pop-to-ebp
 2652     c3/return
 2653 
 2654 test-convert-function-call-with-too-many-outputs:
 2655     # . prologue
 2656     55/push-ebp
 2657     89/<- %ebp 4/r32/esp
 2658     # setup
 2659     (clear-stream _test-input-stream)
 2660     (clear-stream $_test-input-buffered-file->buffer)
 2661     (clear-stream _test-output-stream)
 2662     (clear-stream $_test-output-buffered-file->buffer)
 2663     (clear-stream _test-error-stream)
 2664     (clear-stream $_test-error-buffered-file->buffer)
 2665     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2666     68/push 0/imm32
 2667     68/push 0/imm32
 2668     89/<- %edx 4/r32/esp
 2669     (tailor-exit-descriptor %edx 0x10)
 2670     #
 2671     (write _test-input-stream "fn f {\n")
 2672     (write _test-input-stream "  var x/eax: int <- g\n")
 2673     (write _test-input-stream "}\n")
 2674     (write _test-input-stream "fn g {\n")
 2675     (write _test-input-stream "}\n")
 2676     # convert
 2677     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2678     # registers except esp clobbered at this point
 2679     # restore ed
 2680     89/<- %edx 4/r32/esp
 2681     (flush _test-output-buffered-file)
 2682     (flush _test-error-buffered-file)
 2683 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2689     # check output
 2690     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 2691     (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")
 2692     # check that stop(1) was called
 2693     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 2694     # don't restore from ebp
 2695     81 0/subop/add %esp 8/imm32
 2696     5d/pop-to-ebp
 2697     c3/return
 2698 
 2699 test-convert-function-call-with-missing-output-register:
 2700     # . prologue
 2701     55/push-ebp
 2702     89/<- %ebp 4/r32/esp
 2703     # setup
 2704     (clear-stream _test-input-stream)
 2705     (clear-stream $_test-input-buffered-file->buffer)
 2706     (clear-stream _test-output-stream)
 2707     (clear-stream $_test-output-buffered-file->buffer)
 2708     (clear-stream _test-error-stream)
 2709     (clear-stream $_test-error-buffered-file->buffer)
 2710     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2711     68/push 0/imm32
 2712     68/push 0/imm32
 2713     89/<- %edx 4/r32/esp
 2714     (tailor-exit-descriptor %edx 0x10)
 2715     #
 2716     (write _test-input-stream "fn f {\n")
 2717     (write _test-input-stream "  var x: int\n")
 2718     (write _test-input-stream "  x <- g\n")
 2719     (write _test-input-stream "}\n")
 2720     (write _test-input-stream "fn g -> _/eax: int {\n")
 2721     (write _test-input-stream "}\n")
 2722     # convert
 2723     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2724     # registers except esp clobbered at this point
 2725     # restore ed
 2726     89/<- %edx 4/r32/esp
 2727     (flush _test-output-buffered-file)
 2728     (flush _test-error-buffered-file)
 2729 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2735     # check output
 2736     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 2737     (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")
 2738     # check that stop(1) was called
 2739     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 2740     # don't restore from ebp
 2741     81 0/subop/add %esp 8/imm32
 2742     5d/pop-to-ebp
 2743     c3/return
 2744 
 2745 test-convert-function-call-with-incorrect-output-register:
 2746     # . prologue
 2747     55/push-ebp
 2748     89/<- %ebp 4/r32/esp
 2749     # setup
 2750     (clear-stream _test-input-stream)
 2751     (clear-stream $_test-input-buffered-file->buffer)
 2752     (clear-stream _test-output-stream)
 2753     (clear-stream $_test-output-buffered-file->buffer)
 2754     (clear-stream _test-error-stream)
 2755     (clear-stream $_test-error-buffered-file->buffer)
 2756     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2757     68/push 0/imm32
 2758     68/push 0/imm32
 2759     89/<- %edx 4/r32/esp
 2760     (tailor-exit-descriptor %edx 0x10)
 2761     #
 2762     (write _test-input-stream "fn f {\n")
 2763     (write _test-input-stream "  var x/ecx: int <- g\n")
 2764     (write _test-input-stream "}\n")
 2765     (write _test-input-stream "fn g -> _/eax: int {\n")
 2766     (write _test-input-stream "}\n")
 2767     # convert
 2768     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2769     # registers except esp clobbered at this point
 2770     # restore ed
 2771     89/<- %edx 4/r32/esp
 2772     (flush _test-output-buffered-file)
 2773     (flush _test-error-buffered-file)
 2774 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2780     # check output
 2781     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 2782     (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")
 2783     # check that stop(1) was called
 2784     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 2785     # don't restore from ebp
 2786     81 0/subop/add %esp 8/imm32
 2787     5d/pop-to-ebp
 2788     c3/return
 2789 
 2790 test-convert-function-with-local-var-dereferenced:
 2791     # . prologue
 2792     55/push-ebp
 2793     89/<- %ebp 4/r32/esp
 2794     # setup
 2795     (clear-stream _test-input-stream)
 2796     (clear-stream $_test-input-buffered-file->buffer)
 2797     (clear-stream _test-output-stream)
 2798     (clear-stream $_test-output-buffered-file->buffer)
 2799     #
 2800     (write _test-input-stream "fn foo {\n")
 2801     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2802     (write _test-input-stream "  increment *x\n")
 2803     (write _test-input-stream "}\n")
 2804     # convert
 2805     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2806     (flush _test-output-buffered-file)
 2807 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2813     # check output
 2814     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 2815     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 2816     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 2817     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 2818     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 2819     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 2820     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 2821     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 2822     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 2823     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 2824     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 2825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 2826     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 2827     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 2828     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 2829     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 2830     # . epilogue
 2831     89/<- %esp 5/r32/ebp
 2832     5d/pop-to-ebp
 2833     c3/return
 2834 
 2835 # variables of type 'byte' are not allowed on the stack
 2836 test-convert-function-with-byte-operations:
 2837     # . prologue
 2838     55/push-ebp
 2839     89/<- %ebp 4/r32/esp
 2840     # setup
 2841     (clear-stream _test-input-stream)
 2842     (clear-stream $_test-input-buffered-file->buffer)
 2843     (clear-stream _test-output-stream)
 2844     (clear-stream $_test-output-buffered-file->buffer)
 2845     #
 2846     (write _test-input-stream "fn foo {\n")
 2847     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 2848     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 2849     (write _test-input-stream "  y <- copy-byte x\n")
 2850     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 2851     (write _test-input-stream "  y <- copy-byte *z\n")
 2852     (write _test-input-stream "  copy-byte-to *z, x\n")
 2853     (write _test-input-stream "}\n")
 2854     # convert
 2855     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2856     (flush _test-output-buffered-file)
 2857 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2863     # check output
 2864     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 2865     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 2866     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 2867     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 2868     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 2869     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 2870     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 2871     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 2872     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 2873     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 2874     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 2875     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 2876     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 2877     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 2878     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 2879     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 2880     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 2881     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 2882     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 2883     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 2884     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 2885     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 2886     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 2887     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 2888     # . epilogue
 2889     89/<- %esp 5/r32/ebp
 2890     5d/pop-to-ebp
 2891     c3/return
 2892 
 2893 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 2894 test-copy-byte-var-from-fn-arg:
 2895     # . prologue
 2896     55/push-ebp
 2897     89/<- %ebp 4/r32/esp
 2898     # setup
 2899     (clear-stream _test-input-stream)
 2900     (clear-stream $_test-input-buffered-file->buffer)
 2901     (clear-stream _test-output-stream)
 2902     (clear-stream $_test-output-buffered-file->buffer)
 2903     #
 2904     (write _test-input-stream "fn foo x: byte, y: int {\n")
 2905     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 2906     (write _test-input-stream "  var b/eax: int <- copy y\n")
 2907     (write _test-input-stream "}\n")
 2908     # convert
 2909     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2910     (flush _test-output-buffered-file)
 2911 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2917     # check output
 2918     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 2919     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 2920     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 2921     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 2922     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 2923     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 2924     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 2925     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 2926     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 2927     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 2928     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 2929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 2930     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 2931     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 2932     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 2933     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 2934     # . epilogue
 2935     89/<- %esp 5/r32/ebp
 2936     5d/pop-to-ebp
 2937     c3/return
 2938 
 2939 test-convert-compare-register-with-literal:
 2940     # . prologue
 2941     55/push-ebp
 2942     89/<- %ebp 4/r32/esp
 2943     # setup
 2944     (clear-stream _test-input-stream)
 2945     (clear-stream $_test-input-buffered-file->buffer)
 2946     (clear-stream _test-output-stream)
 2947     (clear-stream $_test-output-buffered-file->buffer)
 2948     #
 2949     (write _test-input-stream "fn foo {\n")
 2950     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 2951     (write _test-input-stream "  compare x, 0\n")
 2952     (write _test-input-stream "}\n")
 2953     # convert
 2954     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2955     (flush _test-output-buffered-file)
 2956 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2962     # check output
 2963     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 2964     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 2965     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 2966     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 2967     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 2968     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 2969     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2970     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 2971     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 2972     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2973     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 2974     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 2975     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 2976     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 2977     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 2978     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 2979     # . epilogue
 2980     89/<- %esp 5/r32/ebp
 2981     5d/pop-to-ebp
 2982     c3/return
 2983 
 2984 test-unknown-variable:
 2985     # . prologue
 2986     55/push-ebp
 2987     89/<- %ebp 4/r32/esp
 2988     # setup
 2989     (clear-stream _test-input-stream)
 2990     (clear-stream $_test-input-buffered-file->buffer)
 2991     (clear-stream _test-output-stream)
 2992     (clear-stream $_test-output-buffered-file->buffer)
 2993     (clear-stream _test-error-stream)
 2994     (clear-stream $_test-error-buffered-file->buffer)
 2995     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2996     68/push 0/imm32
 2997     68/push 0/imm32
 2998     89/<- %edx 4/r32/esp
 2999     (tailor-exit-descriptor %edx 0x10)
 3000     #
 3001     (write _test-input-stream "fn foo {\n")
 3002     (write _test-input-stream "  compare x, 0\n")
 3003     (write _test-input-stream "}\n")
 3004     # convert
 3005     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3006     # registers except esp clobbered at this point
 3007     # restore ed
 3008     89/<- %edx 4/r32/esp
 3009     (flush _test-output-buffered-file)
 3010     (flush _test-error-buffered-file)
 3011 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3017     # check output
 3018     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3019     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3020     # check that stop(1) was called
 3021     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3022     # don't restore from ebp
 3023     81 0/subop/add %esp 8/imm32
 3024     # . epilogue
 3025     5d/pop-to-ebp
 3026     c3/return
 3027 
 3028 test-convert-function-with-local-var-in-block:
 3029     # . prologue
 3030     55/push-ebp
 3031     89/<- %ebp 4/r32/esp
 3032     # setup
 3033     (clear-stream _test-input-stream)
 3034     (clear-stream $_test-input-buffered-file->buffer)
 3035     (clear-stream _test-output-stream)
 3036     (clear-stream $_test-output-buffered-file->buffer)
 3037     #
 3038     (write _test-input-stream "fn foo {\n")
 3039     (write _test-input-stream "  {\n")
 3040     (write _test-input-stream "    var x: int\n")
 3041     (write _test-input-stream "    increment x\n")
 3042     (write _test-input-stream "  }\n")
 3043     (write _test-input-stream "}\n")
 3044     # convert
 3045     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3046     (flush _test-output-buffered-file)
 3047 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3053     # check output
 3054     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 3055     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 3056     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 3057     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 3058     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 3059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 3060     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 3061     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 3062     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 3063     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 3064     (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")
 3065     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 3066     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 3067     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 3068     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 3069     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 3070     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 3071     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 3072     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 3073     # . epilogue
 3074     89/<- %esp 5/r32/ebp
 3075     5d/pop-to-ebp
 3076     c3/return
 3077 
 3078 test-convert-function-with-local-var-in-mem-after-block:
 3079     # . prologue
 3080     55/push-ebp
 3081     89/<- %ebp 4/r32/esp
 3082     # setup
 3083     (clear-stream _test-input-stream)
 3084     (clear-stream $_test-input-buffered-file->buffer)
 3085     (clear-stream _test-output-stream)
 3086     (clear-stream $_test-output-buffered-file->buffer)
 3087     #
 3088     (write _test-input-stream "fn foo {\n")
 3089     (write _test-input-stream "  {\n")
 3090     (write _test-input-stream "    var y: int\n")
 3091     (write _test-input-stream "  }\n")
 3092     (write _test-input-stream "  var x: int\n")
 3093     (write _test-input-stream "  increment x\n")
 3094     (write _test-input-stream "}\n")
 3095     # convert
 3096     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3097     (flush _test-output-buffered-file)
 3098 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3104     # check output
 3105     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 3106     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 3107     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 3108     (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")
 3109     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 3110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 3111     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 3112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 3113     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 3114     (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")
 3115     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 3116     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 3117     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 3118     (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")
 3119     (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")
 3120     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 3121     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 3122     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 3123     (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")
 3124     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 3125     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 3126     # . epilogue
 3127     89/<- %esp 5/r32/ebp
 3128     5d/pop-to-ebp
 3129     c3/return
 3130 
 3131 test-convert-function-with-local-var-in-named-block:
 3132     # . prologue
 3133     55/push-ebp
 3134     89/<- %ebp 4/r32/esp
 3135     # setup
 3136     (clear-stream _test-input-stream)
 3137     (clear-stream $_test-input-buffered-file->buffer)
 3138     (clear-stream _test-output-stream)
 3139     (clear-stream $_test-output-buffered-file->buffer)
 3140     #
 3141     (write _test-input-stream "fn foo {\n")
 3142     (write _test-input-stream "  $bar: {\n")
 3143     (write _test-input-stream "    var x: int\n")
 3144     (write _test-input-stream "    increment x\n")
 3145     (write _test-input-stream "  }\n")
 3146     (write _test-input-stream "}\n")
 3147     # convert
 3148     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3149     (flush _test-output-buffered-file)
 3150 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3156     # check output
 3157     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 3158     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 3159     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 3160     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 3161     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 3162     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 3163     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 3164     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 3165     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 3166     (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")
 3167     (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")
 3168     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 3169     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 3170     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 3171     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 3172     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 3173     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 3174     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 3175     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 3176     # . epilogue
 3177     89/<- %esp 5/r32/ebp
 3178     5d/pop-to-ebp
 3179     c3/return
 3180 
 3181 test-unknown-variable-in-named-block:
 3182     # . prologue
 3183     55/push-ebp
 3184     89/<- %ebp 4/r32/esp
 3185     # setup
 3186     (clear-stream _test-input-stream)
 3187     (clear-stream $_test-input-buffered-file->buffer)
 3188     (clear-stream _test-output-stream)
 3189     (clear-stream $_test-output-buffered-file->buffer)
 3190     (clear-stream _test-error-stream)
 3191     (clear-stream $_test-error-buffered-file->buffer)
 3192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3193     68/push 0/imm32
 3194     68/push 0/imm32
 3195     89/<- %edx 4/r32/esp
 3196     (tailor-exit-descriptor %edx 0x10)
 3197     #
 3198     (write _test-input-stream "fn foo {\n")
 3199     (write _test-input-stream "  $a: {\n")
 3200     (write _test-input-stream "    compare x, 0\n")
 3201     (write _test-input-stream "  }\n")
 3202     (write _test-input-stream "}\n")
 3203     # convert
 3204     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3205     # registers except esp clobbered at this point
 3206     # restore ed
 3207     89/<- %edx 4/r32/esp
 3208     (flush _test-output-buffered-file)
 3209     (flush _test-error-buffered-file)
 3210 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3216     # check output
 3217     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 3218     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 3219     # check that stop(1) was called
 3220     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 3221     # don't restore from ebp
 3222     81 0/subop/add %esp 8/imm32
 3223     # . epilogue
 3224     5d/pop-to-ebp
 3225     c3/return
 3226 
 3227 test-always-shadow-outermost-reg-vars-in-function:
 3228     # . prologue
 3229     55/push-ebp
 3230     89/<- %ebp 4/r32/esp
 3231     # setup
 3232     (clear-stream _test-input-stream)
 3233     (clear-stream $_test-input-buffered-file->buffer)
 3234     (clear-stream _test-output-stream)
 3235     (clear-stream $_test-output-buffered-file->buffer)
 3236     #
 3237     (write _test-input-stream "fn foo {\n")
 3238     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3239     (write _test-input-stream "}\n")
 3240     # convert
 3241     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3242     (flush _test-output-buffered-file)
 3243 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3249     # check output
 3250     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 3251     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 3252     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 3253     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 3254     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 3255     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 3256     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3257     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 3258     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3259     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 3260     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 3261     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 3262     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 3263     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 3264     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 3265     # . epilogue
 3266     89/<- %esp 5/r32/ebp
 3267     5d/pop-to-ebp
 3268     c3/return
 3269 
 3270 test-shadow-local:
 3271     # . prologue
 3272     55/push-ebp
 3273     89/<- %ebp 4/r32/esp
 3274     # setup
 3275     (clear-stream _test-input-stream)
 3276     (clear-stream $_test-input-buffered-file->buffer)
 3277     (clear-stream _test-output-stream)
 3278     (clear-stream $_test-output-buffered-file->buffer)
 3279     #
 3280     (write _test-input-stream "fn foo {\n")
 3281     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3282     (write _test-input-stream "  {\n")
 3283     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 3284     (write _test-input-stream "  }\n")
 3285     (write _test-input-stream "  x <- increment\n")
 3286     (write _test-input-stream "}\n")
 3287     # convert
 3288     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3289     (flush _test-output-buffered-file)
 3290 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3296     # check output
 3297     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 3298     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 3299     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 3300     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 3301     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 3302     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 3303     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 3304     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 3305     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 3306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 3307     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 3308     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 3309     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 3310     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 3311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 3312     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 3313     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 3314     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 3315     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 3316     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 3317     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 3318     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 3319     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 3320     # . epilogue
 3321     89/<- %esp 5/r32/ebp
 3322     5d/pop-to-ebp
 3323     c3/return
 3324 
 3325 test-shadow-name:
 3326     # . prologue
 3327     55/push-ebp
 3328     89/<- %ebp 4/r32/esp
 3329     # setup
 3330     (clear-stream _test-input-stream)
 3331     (clear-stream $_test-input-buffered-file->buffer)
 3332     (clear-stream _test-output-stream)
 3333     (clear-stream $_test-output-buffered-file->buffer)
 3334     #
 3335     (write _test-input-stream "fn foo {\n")
 3336     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3337     (write _test-input-stream "  {\n")
 3338     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 3339     (write _test-input-stream "  }\n")
 3340     (write _test-input-stream "  x <- increment\n")
 3341     (write _test-input-stream "}\n")
 3342     # convert
 3343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3344     (flush _test-output-buffered-file)
 3345 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3351     # check output
 3352     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 3353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 3354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 3355     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 3356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 3357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 3358     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 3359     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 3360     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 3361     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 3362     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 3363     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 3364     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 3365     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 3366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 3367     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 3368     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 3369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 3370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 3371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 3372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 3373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 3374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 3375     # . epilogue
 3376     89/<- %esp 5/r32/ebp
 3377     5d/pop-to-ebp
 3378     c3/return
 3379 
 3380 test-shadow-name-2:
 3381     # . prologue
 3382     55/push-ebp
 3383     89/<- %ebp 4/r32/esp
 3384     # setup
 3385     (clear-stream _test-input-stream)
 3386     (clear-stream $_test-input-buffered-file->buffer)
 3387     (clear-stream _test-output-stream)
 3388     (clear-stream $_test-output-buffered-file->buffer)
 3389     #
 3390     (write _test-input-stream "fn foo {\n")
 3391     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3392     (write _test-input-stream "  {\n")
 3393     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 3394     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 3395     (write _test-input-stream "  }\n")
 3396     (write _test-input-stream "  x <- increment\n")
 3397     (write _test-input-stream "}\n")
 3398     # convert
 3399     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3400     (flush _test-output-buffered-file)
 3401 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3407     # check output
 3408     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 3409     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 3410     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 3411     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 3412     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 3413     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 3414     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 3415     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 3416     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 3417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 3418     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 3419     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 3420     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 3421     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 3422     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 3423     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 3424     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 3425     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 3426     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 3427     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 3428     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 3429     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 3430     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 3431     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 3432     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 3433     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 3434     # . epilogue
 3435     89/<- %esp 5/r32/ebp
 3436     5d/pop-to-ebp
 3437     c3/return
 3438 
 3439 test-do-not-spill-same-register-in-block:
 3440     # . prologue
 3441     55/push-ebp
 3442     89/<- %ebp 4/r32/esp
 3443     # setup
 3444     (clear-stream _test-input-stream)
 3445     (clear-stream $_test-input-buffered-file->buffer)
 3446     (clear-stream _test-output-stream)
 3447     (clear-stream $_test-output-buffered-file->buffer)
 3448     #
 3449     (write _test-input-stream "fn foo {\n")
 3450     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3451     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 3452     (write _test-input-stream "  y <- increment\n")
 3453     (write _test-input-stream "}\n")
 3454     # convert
 3455     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3456     (flush _test-output-buffered-file)
 3457 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3463     # check output
 3464     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 3465     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 3466     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 3467     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 3468     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 3469     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 3470     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 3471     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 3472     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 3473     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 3474     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 3475     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 3476     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 3477     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 3478     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 3479     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 3480     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 3481     # . epilogue
 3482     89/<- %esp 5/r32/ebp
 3483     5d/pop-to-ebp
 3484     c3/return
 3485 
 3486 test-spill-different-register-in-block:
 3487     # . prologue
 3488     55/push-ebp
 3489     89/<- %ebp 4/r32/esp
 3490     # setup
 3491     (clear-stream _test-input-stream)
 3492     (clear-stream $_test-input-buffered-file->buffer)
 3493     (clear-stream _test-output-stream)
 3494     (clear-stream $_test-output-buffered-file->buffer)
 3495     #
 3496     (write _test-input-stream "fn foo {\n")
 3497     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 3498     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 3499     (write _test-input-stream "  y <- increment\n")
 3500     (write _test-input-stream "}\n")
 3501     # convert
 3502     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3503     (flush _test-output-buffered-file)
 3504 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3510     # check output
 3511     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 3512     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 3513     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 3514     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 3515     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 3516     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 3517     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 3518     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 3519     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 3520     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 3521     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 3522     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 3523     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 3524     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 3525     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 3526     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 3527     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 3528     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 3529     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 3530     # . epilogue
 3531     89/<- %esp 5/r32/ebp
 3532     5d/pop-to-ebp
 3533     c3/return
 3534 
 3535 test-convert-function-with-branches-in-block:
 3536     # . prologue
 3537     55/push-ebp
 3538     89/<- %ebp 4/r32/esp
 3539     # setup
 3540     (clear-stream _test-input-stream)
 3541     (clear-stream $_test-input-buffered-file->buffer)
 3542     (clear-stream _test-output-stream)
 3543     (clear-stream $_test-output-buffered-file->buffer)
 3544     #
 3545     (write _test-input-stream "fn foo x: int {\n")
 3546     (write _test-input-stream "  {\n")
 3547     (write _test-input-stream "    break-if->=\n")
 3548     (write _test-input-stream "    loop-if-addr<\n")
 3549     (write _test-input-stream "    increment x\n")
 3550     (write _test-input-stream "    loop\n")
 3551     (write _test-input-stream "  }\n")
 3552     (write _test-input-stream "}\n")
 3553     # convert
 3554     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3555     (flush _test-output-buffered-file)
 3556 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3562     # check output
 3563     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3564     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3565     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3566     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3567     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3568     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3569     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3570     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3571     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3572     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3573     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3574     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3575     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3576     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3577     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3578     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3579     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3580     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3581     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3582     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3583     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3584     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3585     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3586     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3587     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3588     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3589     # . epilogue
 3590     89/<- %esp 5/r32/ebp
 3591     5d/pop-to-ebp
 3592     c3/return
 3593 
 3594 test-convert-function-with-branches-in-block-2:
 3595     # . prologue
 3596     55/push-ebp
 3597     89/<- %ebp 4/r32/esp
 3598     # setup
 3599     (clear-stream _test-input-stream)
 3600     (clear-stream $_test-input-buffered-file->buffer)
 3601     (clear-stream _test-output-stream)
 3602     (clear-stream $_test-output-buffered-file->buffer)
 3603     #
 3604     (write _test-input-stream "fn foo x: int {\n")
 3605     (write _test-input-stream "  {\n")
 3606     (write _test-input-stream "    break-if->=\n")
 3607     (write _test-input-stream "    loop-if-float<\n")
 3608     (write _test-input-stream "    increment x\n")
 3609     (write _test-input-stream "    loop\n")
 3610     (write _test-input-stream "  }\n")
 3611     (write _test-input-stream "}\n")
 3612     # convert
 3613     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3614     (flush _test-output-buffered-file)
 3615 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3621     # check output
 3622     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3623     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3624     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3625     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3626     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3627     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3628     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3629     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3630     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3631     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3632     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3633     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3634     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3635     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3636     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3637     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3638     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3639     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3640     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3641     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3642     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3643     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3644     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3645     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3646     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3647     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3648     # . epilogue
 3649     89/<- %esp 5/r32/ebp
 3650     5d/pop-to-ebp
 3651     c3/return
 3652 
 3653 test-convert-function-with-branches-in-named-block:
 3654     # . prologue
 3655     55/push-ebp
 3656     89/<- %ebp 4/r32/esp
 3657     # setup
 3658     (clear-stream _test-input-stream)
 3659     (clear-stream $_test-input-buffered-file->buffer)
 3660     (clear-stream _test-output-stream)
 3661     (clear-stream $_test-output-buffered-file->buffer)
 3662     #
 3663     (write _test-input-stream "fn foo x: int {\n")
 3664     (write _test-input-stream "  $bar: {\n")
 3665     (write _test-input-stream "    break-if->= $bar\n")
 3666     (write _test-input-stream "    loop-if-addr< $bar\n")
 3667     (write _test-input-stream "    increment x\n")
 3668     (write _test-input-stream "    loop\n")
 3669     (write _test-input-stream "  }\n")
 3670     (write _test-input-stream "}\n")
 3671     # convert
 3672     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3673     (flush _test-output-buffered-file)
 3674 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3680     # check output
 3681     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 3682     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 3683     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 3684     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 3685     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 3686     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 3687     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 3688     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 3689     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 3690     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 3691     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 3692     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 3693     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 3694     (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")
 3695     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 3696     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 3697     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 3698     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 3699     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 3700     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 3701     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 3702     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 3703     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 3704     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 3705     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 3706     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 3707     # . epilogue
 3708     89/<- %esp 5/r32/ebp
 3709     5d/pop-to-ebp
 3710     c3/return
 3711 
 3712 test-convert-function-with-var-in-nested-block:
 3713     # . prologue
 3714     55/push-ebp
 3715     89/<- %ebp 4/r32/esp
 3716     # setup
 3717     (clear-stream _test-input-stream)
 3718     (clear-stream $_test-input-buffered-file->buffer)
 3719     (clear-stream _test-output-stream)
 3720     (clear-stream $_test-output-buffered-file->buffer)
 3721     #
 3722     (write _test-input-stream "fn foo x: int {\n")
 3723     (write _test-input-stream "  {\n")
 3724     (write _test-input-stream "    {\n")
 3725     (write _test-input-stream "      var x: int\n")
 3726     (write _test-input-stream "      increment x\n")
 3727     (write _test-input-stream "    }\n")
 3728     (write _test-input-stream "  }\n")
 3729     (write _test-input-stream "}\n")
 3730     # convert
 3731     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3732     (flush _test-output-buffered-file)
 3733 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3739     # check output
 3740     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 3741     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 3742     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 3743     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 3744     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 3745     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 3746     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 3747     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 3748     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 3749     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 3750     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 3751     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 3752     (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")
 3753     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 3754     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 3755     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 3756     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 3757     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 3758     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 3759     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 3760     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 3761     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 3762     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 3763     # . epilogue
 3764     89/<- %esp 5/r32/ebp
 3765     5d/pop-to-ebp
 3766     c3/return
 3767 
 3768 test-convert-function-with-multiple-vars-in-nested-blocks:
 3769     # . prologue
 3770     55/push-ebp
 3771     89/<- %ebp 4/r32/esp
 3772     # setup
 3773     (clear-stream _test-input-stream)
 3774     (clear-stream $_test-input-buffered-file->buffer)
 3775     (clear-stream _test-output-stream)
 3776     (clear-stream $_test-output-buffered-file->buffer)
 3777     #
 3778     (write _test-input-stream "fn foo x: int {\n")
 3779     (write _test-input-stream "  {\n")
 3780     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 3781     (write _test-input-stream "    {\n")
 3782     (write _test-input-stream "      var y: int\n")
 3783     (write _test-input-stream "      x <- add y\n")
 3784     (write _test-input-stream "    }\n")
 3785     (write _test-input-stream "  }\n")
 3786     (write _test-input-stream "}\n")
 3787     # convert
 3788     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3789     (flush _test-output-buffered-file)
 3790 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3796     # check output
 3797     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 3798     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 3799     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 3800     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 3801     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 3802     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 3803     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 3804     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 3805     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 3806     (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")
 3807     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 3808     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 3809     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 3810     (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")
 3811     (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")
 3812     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 3813     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 3814     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 3815     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 3816     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 3817     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 3818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 3819     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 3820     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 3821     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 3822     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 3823     # . epilogue
 3824     89/<- %esp 5/r32/ebp
 3825     5d/pop-to-ebp
 3826     c3/return
 3827 
 3828 test-convert-function-with-branches-and-local-vars:
 3829     # A conditional 'break' after a 'var' in a block is converted into a
 3830     # nested block that performs all necessary cleanup before jumping. This
 3831     # results in some ugly code duplication.
 3832     # . prologue
 3833     55/push-ebp
 3834     89/<- %ebp 4/r32/esp
 3835     # setup
 3836     (clear-stream _test-input-stream)
 3837     (clear-stream $_test-input-buffered-file->buffer)
 3838     (clear-stream _test-output-stream)
 3839     (clear-stream $_test-output-buffered-file->buffer)
 3840     #
 3841     (write _test-input-stream "fn foo {\n")
 3842     (write _test-input-stream "  {\n")
 3843     (write _test-input-stream "    var x: int\n")
 3844     (write _test-input-stream "    break-if->=\n")
 3845     (write _test-input-stream "    increment x\n")
 3846     (write _test-input-stream "  }\n")
 3847     (write _test-input-stream "}\n")
 3848     # convert
 3849     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3850     (flush _test-output-buffered-file)
 3851 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3857     # check output
 3858     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 3859     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 3860     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 3861     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 3862     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 3863     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 3864     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 3865     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 3866     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 3867     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 3868     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 3869     (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")
 3870     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 3871     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 3872     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 3873     (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")
 3874     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 3875     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 3876     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 3877     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 3878     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 3879     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 3880     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 3881     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 3882     # . epilogue
 3883     89/<- %esp 5/r32/ebp
 3884     5d/pop-to-ebp
 3885     c3/return
 3886 
 3887 test-convert-function-with-conditional-loops-and-local-vars:
 3888     # A conditional 'loop' after a 'var' in a block is converted into a nested
 3889     # block that performs all necessary cleanup before jumping. This results
 3890     # in some ugly code duplication.
 3891     # . prologue
 3892     55/push-ebp
 3893     89/<- %ebp 4/r32/esp
 3894     # setup
 3895     (clear-stream _test-input-stream)
 3896     (clear-stream $_test-input-buffered-file->buffer)
 3897     (clear-stream _test-output-stream)
 3898     (clear-stream $_test-output-buffered-file->buffer)
 3899     #
 3900     (write _test-input-stream "fn foo {\n")
 3901     (write _test-input-stream "  {\n")
 3902     (write _test-input-stream "    var x: int\n")
 3903     (write _test-input-stream "    loop-if->=\n")
 3904     (write _test-input-stream "    increment x\n")
 3905     (write _test-input-stream "  }\n")
 3906     (write _test-input-stream "}\n")
 3907     # convert
 3908     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3909     (flush _test-output-buffered-file)
 3910 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3916     # check output
 3917     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 3918     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 3919     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 3920     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 3921     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 3922     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 3923     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 3924     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 3925     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 3926     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 3927     (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")
 3928     (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")
 3929     (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")
 3930     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 3931     (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")
 3932     (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")
 3933     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 3934     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 3935     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 3936     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 3937     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 3938     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 3939     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 3940     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 3941     # . epilogue
 3942     89/<- %esp 5/r32/ebp
 3943     5d/pop-to-ebp
 3944     c3/return
 3945 
 3946 test-convert-function-with-unconditional-loops-and-local-vars:
 3947     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 3948     # regular block cleanup. Any instructions after 'loop' are dead and
 3949     # therefore skipped.
 3950     # . prologue
 3951     55/push-ebp
 3952     89/<- %ebp 4/r32/esp
 3953     # setup
 3954     (clear-stream _test-input-stream)
 3955     (clear-stream $_test-input-buffered-file->buffer)
 3956     (clear-stream _test-output-stream)
 3957     (clear-stream $_test-output-buffered-file->buffer)
 3958     #
 3959     (write _test-input-stream "fn foo {\n")
 3960     (write _test-input-stream "  {\n")
 3961     (write _test-input-stream "    var x: int\n")
 3962     (write _test-input-stream "    loop\n")
 3963     (write _test-input-stream "    increment x\n")
 3964     (write _test-input-stream "  }\n")
 3965     (write _test-input-stream "}\n")
 3966     # convert
 3967     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3968     (flush _test-output-buffered-file)
 3969 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3975     # check output
 3976     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 3977     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 3978     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 3979     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 3980     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 3981     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 3982     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 3983     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 3984     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 3985     (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")
 3986     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 3987     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 3988     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 3989     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 3990     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 3991     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 3992     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 3993     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 3994     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 3995     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 3996     # . epilogue
 3997     89/<- %esp 5/r32/ebp
 3998     5d/pop-to-ebp
 3999     c3/return
 4000 
 4001 test-convert-function-with-branches-and-loops-and-local-vars:
 4002     # . prologue
 4003     55/push-ebp
 4004     89/<- %ebp 4/r32/esp
 4005     # setup
 4006     (clear-stream _test-input-stream)
 4007     (clear-stream $_test-input-buffered-file->buffer)
 4008     (clear-stream _test-output-stream)
 4009     (clear-stream $_test-output-buffered-file->buffer)
 4010     #
 4011     (write _test-input-stream "fn foo {\n")
 4012     (write _test-input-stream "  {\n")
 4013     (write _test-input-stream "    var x: int\n")
 4014     (write _test-input-stream "    break-if->=\n")
 4015     (write _test-input-stream "    increment x\n")
 4016     (write _test-input-stream "    loop\n")
 4017     (write _test-input-stream "  }\n")
 4018     (write _test-input-stream "}\n")
 4019     # convert
 4020     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4021     (flush _test-output-buffered-file)
 4022 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4028     # check output
 4029     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4030     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4031     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4032     (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")
 4033     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4034     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4035     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4036     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4037     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4038     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4039     (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")
 4040     (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")
 4041     (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")
 4042     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 4043     (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")
 4044     (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")
 4045     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 4046     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 4047     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 4048     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 4049     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 4050     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 4051     (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")
 4052     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 4053     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 4054     # . epilogue
 4055     89/<- %esp 5/r32/ebp
 4056     5d/pop-to-ebp
 4057     c3/return
 4058 
 4059 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 4060     # . prologue
 4061     55/push-ebp
 4062     89/<- %ebp 4/r32/esp
 4063     # setup
 4064     (clear-stream _test-input-stream)
 4065     (clear-stream $_test-input-buffered-file->buffer)
 4066     (clear-stream _test-output-stream)
 4067     (clear-stream $_test-output-buffered-file->buffer)
 4068     #
 4069     (write _test-input-stream "fn foo {\n")
 4070     (write _test-input-stream "  a: {\n")
 4071     (write _test-input-stream "    var x: int\n")
 4072     (write _test-input-stream "    {\n")
 4073     (write _test-input-stream "      var y: int\n")
 4074     (write _test-input-stream "      break-if->= a\n")
 4075     (write _test-input-stream "      increment x\n")
 4076     (write _test-input-stream "      loop\n")
 4077     (write _test-input-stream "    }\n")
 4078     (write _test-input-stream "  }\n")
 4079     (write _test-input-stream "}\n")
 4080     # convert
 4081     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4082     (flush _test-output-buffered-file)
 4083 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4089     # check output
 4090     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 4091     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 4092     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 4093     (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")
 4094     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 4095     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 4096     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 4097     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 4098     (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")
 4099     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 4100     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 4101     (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")
 4102     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 4103     (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")
 4104     (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")
 4105     (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")
 4106     (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")
 4107     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 4108     (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")
 4109     (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")
 4110     (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")
 4111     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 4112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 4113     (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")
 4114     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 4115     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 4116     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 4117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 4118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 4119     (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")
 4120     (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")
 4121     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 4122     # . epilogue
 4123     89/<- %esp 5/r32/ebp
 4124     5d/pop-to-ebp
 4125     c3/return
 4126 
 4127 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 4128     # . prologue
 4129     55/push-ebp
 4130     89/<- %ebp 4/r32/esp
 4131     # setup
 4132     (clear-stream _test-input-stream)
 4133     (clear-stream $_test-input-buffered-file->buffer)
 4134     (clear-stream _test-output-stream)
 4135     (clear-stream $_test-output-buffered-file->buffer)
 4136     # non-local conditional branch from a block without a local variable,
 4137     # unwinding a local on the stack
 4138     (write _test-input-stream "fn foo {\n")
 4139     (write _test-input-stream "  a: {\n")
 4140     (write _test-input-stream "    var x: int\n")
 4141     (write _test-input-stream "    {\n")
 4142     (write _test-input-stream "      break-if->= a\n")
 4143     (write _test-input-stream "    }\n")
 4144     (write _test-input-stream "  }\n")
 4145     (write _test-input-stream "}\n")
 4146     # convert
 4147     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4148     (flush _test-output-buffered-file)
 4149 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4155     # check output
 4156     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 4157     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 4158     (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")
 4159     (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")
 4160     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 4161     (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")
 4162     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 4163     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 4164     (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")
 4165     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 4166     (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")
 4167     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 4168     (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")
 4169     (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")
 4170     (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")
 4171     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 4172     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 4173     (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")
 4174     (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")
 4175     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 4176     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 4177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 4178     (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")
 4179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 4180     (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")
 4181     (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")
 4182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 4183     # . epilogue
 4184     89/<- %esp 5/r32/ebp
 4185     5d/pop-to-ebp
 4186     c3/return
 4187 
 4188 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 4189     # . prologue
 4190     55/push-ebp
 4191     89/<- %ebp 4/r32/esp
 4192     # setup
 4193     (clear-stream _test-input-stream)
 4194     (clear-stream $_test-input-buffered-file->buffer)
 4195     (clear-stream _test-output-stream)
 4196     (clear-stream $_test-output-buffered-file->buffer)
 4197     # non-local unconditional branch from a block without a local variable,
 4198     # unwinding a local on the stack
 4199     (write _test-input-stream "fn foo {\n")
 4200     (write _test-input-stream "  a: {\n")
 4201     (write _test-input-stream "    var x: int\n")
 4202     (write _test-input-stream "    {\n")
 4203     (write _test-input-stream "      break a\n")
 4204     (write _test-input-stream "    }\n")
 4205     (write _test-input-stream "  }\n")
 4206     (write _test-input-stream "}\n")
 4207     # convert
 4208     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4209     (flush _test-output-buffered-file)
 4210 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4216     # check output
 4217     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 4218     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 4219     (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")
 4220     (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")
 4221     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 4222     (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")
 4223     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 4224     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 4225     (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")
 4226     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 4227     (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")
 4228     (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")
 4229     (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")
 4230     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 4231     (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")
 4232     (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")
 4233     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 4234     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 4235     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 4236     (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")
 4237     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 4238     (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")
 4239     (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")
 4240     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 4241     # . epilogue
 4242     89/<- %esp 5/r32/ebp
 4243     5d/pop-to-ebp
 4244     c3/return
 4245 
 4246 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 4247     # . prologue
 4248     55/push-ebp
 4249     89/<- %ebp 4/r32/esp
 4250     # setup
 4251     (clear-stream _test-input-stream)
 4252     (clear-stream $_test-input-buffered-file->buffer)
 4253     (clear-stream _test-output-stream)
 4254     (clear-stream $_test-output-buffered-file->buffer)
 4255     #
 4256     (write _test-input-stream "fn foo {\n")
 4257     (write _test-input-stream "  a: {\n")
 4258     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 4259     (write _test-input-stream "    {\n")
 4260     (write _test-input-stream "      break a\n")
 4261     (write _test-input-stream "    }\n")
 4262     (write _test-input-stream "  }\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-nonlocal-branches-and-loops-and-local-vars-4/0")
 4275     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 4276     (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")
 4277     (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")
 4278     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 4279     (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")
 4280     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 4281     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 4282     (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")
 4283     (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")
 4284     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 4285     (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")
 4286     (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")
 4287     (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")
 4288     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 4289     (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")
 4290     (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")
 4291     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 4292     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 4293     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 4294     (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")
 4295     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 4296     (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")
 4297     (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")
 4298     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 4299     # . epilogue
 4300     89/<- %esp 5/r32/ebp
 4301     5d/pop-to-ebp
 4302     c3/return
 4303 
 4304 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 4305     # . prologue
 4306     55/push-ebp
 4307     89/<- %ebp 4/r32/esp
 4308     # setup
 4309     (clear-stream _test-input-stream)
 4310     (clear-stream $_test-input-buffered-file->buffer)
 4311     (clear-stream _test-output-stream)
 4312     (clear-stream $_test-output-buffered-file->buffer)
 4313     #
 4314     (write _test-input-stream "fn foo {\n")
 4315     (write _test-input-stream "  a: {\n")
 4316     (write _test-input-stream "    var x: int\n")
 4317     (write _test-input-stream "    {\n")
 4318     (write _test-input-stream "      var y: int\n")
 4319     (write _test-input-stream "      break a\n")
 4320     (write _test-input-stream "      increment x\n")
 4321     (write _test-input-stream "    }\n")
 4322     (write _test-input-stream "  }\n")
 4323     (write _test-input-stream "}\n")
 4324     # convert
 4325     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4326     (flush _test-output-buffered-file)
 4327 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4333     # check output
 4334     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 4335     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 4336     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 4337     (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")
 4338     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 4339     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 4340     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 4341     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 4342     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 4343     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 4344     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 4345     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 4346     (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")
 4347     (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")
 4348     (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")
 4349     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 4350     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 4351     (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")
 4352     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 4353     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 4354     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 4355     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 4356     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 4357     (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")
 4358     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 4359     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 4360     # . epilogue
 4361     89/<- %esp 5/r32/ebp
 4362     5d/pop-to-ebp
 4363     c3/return
 4364 
 4365 test-convert-function-with-unconditional-break-and-local-vars:
 4366     # . prologue
 4367     55/push-ebp
 4368     89/<- %ebp 4/r32/esp
 4369     # setup
 4370     (clear-stream _test-input-stream)
 4371     (clear-stream $_test-input-buffered-file->buffer)
 4372     (clear-stream _test-output-stream)
 4373     (clear-stream $_test-output-buffered-file->buffer)
 4374     #
 4375     (write _test-input-stream "fn foo {\n")
 4376     (write _test-input-stream "  {\n")
 4377     (write _test-input-stream "    var x: int\n")
 4378     (write _test-input-stream "    {\n")
 4379     (write _test-input-stream "      var y: int\n")
 4380     (write _test-input-stream "      break\n")
 4381     (write _test-input-stream "      increment x\n")
 4382     (write _test-input-stream "    }\n")
 4383     (write _test-input-stream "  }\n")
 4384     (write _test-input-stream "}\n")
 4385     # convert
 4386     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4387     (flush _test-output-buffered-file)
 4388 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4394     # check output
 4395     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 4396     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 4397     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 4398     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 4399     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 4400     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 4401     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 4402     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 4403     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 4404     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 4405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 4406     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 4407     (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")
 4408     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 4409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 4410     (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")
 4411     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 4412     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 4413     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 4414     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 4415     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 4416     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 4417     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 4418     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 4419     # . epilogue
 4420     89/<- %esp 5/r32/ebp
 4421     5d/pop-to-ebp
 4422     c3/return
 4423 
 4424 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 4425     # . prologue
 4426     55/push-ebp
 4427     89/<- %ebp 4/r32/esp
 4428     # setup
 4429     (clear-stream _test-input-stream)
 4430     (clear-stream $_test-input-buffered-file->buffer)
 4431     (clear-stream _test-output-stream)
 4432     (clear-stream $_test-output-buffered-file->buffer)
 4433     #
 4434     (write _test-input-stream "fn foo {\n")
 4435     (write _test-input-stream "  a: {\n")
 4436     (write _test-input-stream "    var x: int\n")
 4437     (write _test-input-stream "    {\n")
 4438     (write _test-input-stream "      var y: int\n")
 4439     (write _test-input-stream "      loop a\n")
 4440     (write _test-input-stream "      increment x\n")
 4441     (write _test-input-stream "    }\n")
 4442     (write _test-input-stream "  }\n")
 4443     (write _test-input-stream "}\n")
 4444     # convert
 4445     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4446     (flush _test-output-buffered-file)
 4447 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4453     # check output
 4454     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 4455     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 4456     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 4457     (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")
 4458     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 4459     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 4460     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 4461     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 4462     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 4463     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 4464     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 4465     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 4466     (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")
 4467     (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")
 4468     (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")
 4469     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 4470     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 4471     (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")
 4472     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 4473     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 4474     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 4475     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 4476     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 4477     (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")
 4478     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 4479     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 4480     # . epilogue
 4481     89/<- %esp 5/r32/ebp
 4482     5d/pop-to-ebp
 4483     c3/return
 4484 
 4485 test-convert-function-with-local-array-var-in-mem:
 4486     # . prologue
 4487     55/push-ebp
 4488     89/<- %ebp 4/r32/esp
 4489     # setup
 4490     (clear-stream _test-input-stream)
 4491     (clear-stream $_test-input-buffered-file->buffer)
 4492     (clear-stream _test-output-stream)
 4493     (clear-stream $_test-output-buffered-file->buffer)
 4494     #
 4495     (write _test-input-stream "fn foo {\n")
 4496     (write _test-input-stream "  var x: (array int 3)\n")
 4497     (write _test-input-stream "}\n")
 4498     # convert
 4499     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4500     (flush _test-output-buffered-file)
 4501 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4507     # check output
 4508     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 4509     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 4510     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 4511     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 4512     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 4513     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 4514     # define x
 4515     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 4516     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 4517     # reclaim x
 4518     (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")
 4519     #
 4520     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 4521     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 4522     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 4523     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 4524     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 4525     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 4526     # . epilogue
 4527     89/<- %esp 5/r32/ebp
 4528     5d/pop-to-ebp
 4529     c3/return
 4530 
 4531 test-array-size-in-hex:
 4532     # . prologue
 4533     55/push-ebp
 4534     89/<- %ebp 4/r32/esp
 4535     # setup
 4536     (clear-stream _test-input-stream)
 4537     (clear-stream $_test-input-buffered-file->buffer)
 4538     (clear-stream _test-output-stream)
 4539     (clear-stream $_test-output-buffered-file->buffer)
 4540     (clear-stream _test-error-stream)
 4541     (clear-stream $_test-error-buffered-file->buffer)
 4542     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4543     68/push 0/imm32
 4544     68/push 0/imm32
 4545     89/<- %edx 4/r32/esp
 4546     (tailor-exit-descriptor %edx 0x10)
 4547     #
 4548     (write _test-input-stream "fn foo {\n")
 4549     (write _test-input-stream "  var x: (array int 10)\n")
 4550     (write _test-input-stream "}\n")
 4551     # convert
 4552     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4553     # registers except esp clobbered at this point
 4554     # restore ed
 4555     89/<- %edx 4/r32/esp
 4556     (flush _test-output-buffered-file)
 4557     (flush _test-error-buffered-file)
 4558 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4564     # check output
 4565     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 4566     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-array-size-in-hex: error message")
 4567     # check that stop(1) was called
 4568     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 4569     # don't restore from ebp
 4570     81 0/subop/add %esp 8/imm32
 4571     # . epilogue
 4572     5d/pop-to-ebp
 4573     c3/return
 4574 
 4575 test-convert-function-with-populate:
 4576     # . prologue
 4577     55/push-ebp
 4578     89/<- %ebp 4/r32/esp
 4579     # setup
 4580     (clear-stream _test-input-stream)
 4581     (clear-stream $_test-input-buffered-file->buffer)
 4582     (clear-stream _test-output-stream)
 4583     (clear-stream $_test-output-buffered-file->buffer)
 4584     #
 4585     (write _test-input-stream "fn foo {\n")
 4586     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 4587     (write _test-input-stream "  populate x, 7\n")
 4588     (write _test-input-stream "}\n")
 4589     # convert
 4590     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4591     (flush _test-output-buffered-file)
 4592 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4598     # check output
 4599     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 4600     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 4601     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 4602     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 4603     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 4604     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 4605     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 4606     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 4607     (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)
 4608     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 4609     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 4610     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 4611     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 4612     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 4613     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 4614     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 4615     # . epilogue
 4616     89/<- %esp 5/r32/ebp
 4617     5d/pop-to-ebp
 4618     c3/return
 4619 
 4620 # special-case for size(byte) when allocating array
 4621 test-convert-function-with-local-array-of-bytes-in-mem:
 4622     # . prologue
 4623     55/push-ebp
 4624     89/<- %ebp 4/r32/esp
 4625     # setup
 4626     (clear-stream _test-input-stream)
 4627     (clear-stream $_test-input-buffered-file->buffer)
 4628     (clear-stream _test-output-stream)
 4629     (clear-stream $_test-output-buffered-file->buffer)
 4630     #
 4631     (write _test-input-stream "fn foo {\n")
 4632     (write _test-input-stream "  var x: (array byte 3)\n")
 4633     (write _test-input-stream "}\n")
 4634     # convert
 4635     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4636     (flush _test-output-buffered-file)
 4637 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4643     # check output
 4644     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 4645     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 4646     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 4647     (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")
 4648     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 4649     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 4650     # define x
 4651     (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")
 4652     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 4653     # reclaim x
 4654     (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")
 4655     #
 4656     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 4657     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 4658     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 4659     (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")
 4660     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 4661     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 4662     # . epilogue
 4663     89/<- %esp 5/r32/ebp
 4664     5d/pop-to-ebp
 4665     c3/return
 4666 
 4667 test-convert-address:
 4668     # . prologue
 4669     55/push-ebp
 4670     89/<- %ebp 4/r32/esp
 4671     # setup
 4672     (clear-stream _test-input-stream)
 4673     (clear-stream $_test-input-buffered-file->buffer)
 4674     (clear-stream _test-output-stream)
 4675     (clear-stream $_test-output-buffered-file->buffer)
 4676     #
 4677     (write _test-input-stream "fn foo {\n")
 4678     (write _test-input-stream "  var a: int\n")
 4679     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 4680     (write _test-input-stream "}\n")
 4681     # convert
 4682     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4683     (flush _test-output-buffered-file)
 4684 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4690     # check output
 4691     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 4692     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 4693     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 4694     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 4695     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 4696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 4697     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 4698     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 4699     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 4700     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 4701     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 4702     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 4703     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 4704     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 4705     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 4706     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 4707     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 4708     # . epilogue
 4709     89/<- %esp 5/r32/ebp
 4710     5d/pop-to-ebp
 4711     c3/return
 4712 
 4713 test-convert-floating-point-convert:
 4714     # . prologue
 4715     55/push-ebp
 4716     89/<- %ebp 4/r32/esp
 4717     # setup
 4718     (clear-stream _test-input-stream)
 4719     (clear-stream $_test-input-buffered-file->buffer)
 4720     (clear-stream _test-output-stream)
 4721     (clear-stream $_test-output-buffered-file->buffer)
 4722     #
 4723     (write _test-input-stream "fn foo {\n")
 4724     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4725     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4726     (write _test-input-stream "}\n")
 4727     # convert
 4728     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4729     (flush _test-output-buffered-file)
 4730 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4736     # check output
 4737     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 4738     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 4739     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 4740     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 4741     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 4742     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 4743     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 4744     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 4745     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 4746     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 4747     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 4748     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 4749     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 4750     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 4751     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 4752     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 4753     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 4754     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 4755     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 4756     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 4757     # . epilogue
 4758     89/<- %esp 5/r32/ebp
 4759     5d/pop-to-ebp
 4760     c3/return
 4761 
 4762 test-convert-floating-point-convert-2:
 4763     # . prologue
 4764     55/push-ebp
 4765     89/<- %ebp 4/r32/esp
 4766     # setup
 4767     (clear-stream _test-input-stream)
 4768     (clear-stream $_test-input-buffered-file->buffer)
 4769     (clear-stream _test-output-stream)
 4770     (clear-stream $_test-output-buffered-file->buffer)
 4771     #
 4772     (write _test-input-stream "fn foo {\n")
 4773     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4774     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4775     (write _test-input-stream "  a <- convert b\n")
 4776     (write _test-input-stream "}\n")
 4777     # convert
 4778     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4779     (flush _test-output-buffered-file)
 4780 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4786     # check output
 4787     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 4788     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 4789     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 4790     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 4791     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 4792     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 4793     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 4794     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 4795     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 4796     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 4797     (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")
 4798     (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")
 4799     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 4800     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 4801     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 4802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 4803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 4804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 4805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 4806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 4807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 4808     # . epilogue
 4809     89/<- %esp 5/r32/ebp
 4810     5d/pop-to-ebp
 4811     c3/return
 4812 
 4813 test-convert-floating-point-operation:
 4814     # . prologue
 4815     55/push-ebp
 4816     89/<- %ebp 4/r32/esp
 4817     # setup
 4818     (clear-stream _test-input-stream)
 4819     (clear-stream $_test-input-buffered-file->buffer)
 4820     (clear-stream _test-output-stream)
 4821     (clear-stream $_test-output-buffered-file->buffer)
 4822     #
 4823     (write _test-input-stream "fn f {\n")
 4824     (write _test-input-stream "  var m: float\n")
 4825     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 4826     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 4827     (write _test-input-stream "  x <- copy y\n")
 4828     (write _test-input-stream "  copy-to m, y\n")
 4829     (write _test-input-stream "  x <- add y\n")
 4830     (write _test-input-stream "  x <- add m\n")
 4831     (write _test-input-stream "  x <- subtract y\n")
 4832     (write _test-input-stream "  x <- subtract m\n")
 4833     (write _test-input-stream "  x <- multiply y\n")
 4834     (write _test-input-stream "  x <- multiply m\n")
 4835     (write _test-input-stream "  x <- divide y\n")
 4836     (write _test-input-stream "  x <- divide m\n")
 4837     (write _test-input-stream "  x <- reciprocal y\n")
 4838     (write _test-input-stream "  x <- reciprocal m\n")
 4839     (write _test-input-stream "  x <- square-root y\n")
 4840     (write _test-input-stream "  x <- square-root m\n")
 4841     (write _test-input-stream "  x <- inverse-square-root y\n")
 4842     (write _test-input-stream "  x <- inverse-square-root m\n")
 4843     (write _test-input-stream "  x <- max y\n")
 4844     (write _test-input-stream "  x <- max m\n")
 4845     (write _test-input-stream "  x <- min y\n")
 4846     (write _test-input-stream "  x <- min m\n")
 4847     (write _test-input-stream "  compare x, y\n")
 4848     (write _test-input-stream "  compare x, m\n")
 4849     (write _test-input-stream "}\n")
 4850     # convert
 4851     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4852     (flush _test-output-buffered-file)
 4853 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4859     # check output
 4860     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 4861     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 4862     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 4863     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 4864     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 4865     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 4866     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 4867     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 4868     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 4869     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 4870     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 4871     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 4872     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 4873     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 4874     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 4875     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 4876     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 4877     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 4878     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 4879     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 4880     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 4881     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 4882     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 4883     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 4884     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 4885     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 4886     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 4887     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 4888     (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")
 4889     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 4890     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 4891     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 4892     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 4893     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 4894     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 4895     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 4896     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 4897     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 4898     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 4899     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 4900     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 4901     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 4902     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 4903     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 4904     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 4905     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 4906     # . epilogue
 4907     89/<- %esp 5/r32/ebp
 4908     5d/pop-to-ebp
 4909     c3/return
 4910 
 4911 test-convert-floating-point-dereferenced:
 4912     # . prologue
 4913     55/push-ebp
 4914     89/<- %ebp 4/r32/esp
 4915     # setup
 4916     (clear-stream _test-input-stream)
 4917     (clear-stream $_test-input-buffered-file->buffer)
 4918     (clear-stream _test-output-stream)
 4919     (clear-stream $_test-output-buffered-file->buffer)
 4920     #
 4921     (write _test-input-stream "fn f {\n")
 4922     (write _test-input-stream "  var m: float\n")
 4923     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 4924     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 4925     (write _test-input-stream "  x <- multiply *y\n")
 4926     (write _test-input-stream "}\n")
 4927     # convert
 4928     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4929     (flush _test-output-buffered-file)
 4930 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4936     # check output
 4937     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 4938     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 4939     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 4940     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 4941     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 4942     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 4943     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 4944     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 4945     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 4946     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 4947     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 4948     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 4949     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 4950     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 4951     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 4952     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 4953     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 4954     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 4955     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 4956     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 4957     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 4958     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 4959     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 4960     # . epilogue
 4961     89/<- %esp 5/r32/ebp
 4962     5d/pop-to-ebp
 4963     c3/return
 4964 
 4965 test-convert-length-of-array:
 4966     # . prologue
 4967     55/push-ebp
 4968     89/<- %ebp 4/r32/esp
 4969     # setup
 4970     (clear-stream _test-input-stream)
 4971     (clear-stream $_test-input-buffered-file->buffer)
 4972     (clear-stream _test-output-stream)
 4973     (clear-stream $_test-output-buffered-file->buffer)
 4974     #
 4975     (write _test-input-stream "fn foo a: (addr array int) {\n")
 4976     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 4977     (write _test-input-stream "  var c/eax: int <- length b\n")
 4978     (write _test-input-stream "}\n")
 4979     # convert
 4980     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4981     (flush _test-output-buffered-file)
 4982 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4988     # check output
 4989     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 4990     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 4991     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 4992     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 4993     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 4994     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 4995     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 4996     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 4997     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 4998     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 4999     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 5000     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 5001     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 5002     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 5003     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 5004     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 5005     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 5006     # . epilogue
 5007     89/<- %esp 5/r32/ebp
 5008     5d/pop-to-ebp
 5009     c3/return
 5010 
 5011 # special-case for size(byte) when computing array length
 5012 test-convert-length-of-array-of-bytes:
 5013     # . prologue
 5014     55/push-ebp
 5015     89/<- %ebp 4/r32/esp
 5016     # setup
 5017     (clear-stream _test-input-stream)
 5018     (clear-stream $_test-input-buffered-file->buffer)
 5019     (clear-stream _test-output-stream)
 5020     (clear-stream $_test-output-buffered-file->buffer)
 5021     #
 5022     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 5023     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 5024     (write _test-input-stream "  var c/eax: int <- length b\n")
 5025     (write _test-input-stream "}\n")
 5026     # convert
 5027     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5028     (flush _test-output-buffered-file)
 5029 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5035     # check output
 5036     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 5037     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 5038     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 5039     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 5040     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 5041     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 5042     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 5043     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 5044     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 5045     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 5046     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 5047     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 5048     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 5049     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 5050     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 5051     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 5052     # . epilogue
 5053     89/<- %esp 5/r32/ebp
 5054     5d/pop-to-ebp
 5055     c3/return
 5056 
 5057 test-convert-length-of-array-on-stack:
 5058     # . prologue
 5059     55/push-ebp
 5060     89/<- %ebp 4/r32/esp
 5061     # setup
 5062     (clear-stream _test-input-stream)
 5063     (clear-stream $_test-input-buffered-file->buffer)
 5064     (clear-stream _test-output-stream)
 5065     (clear-stream $_test-output-buffered-file->buffer)
 5066     #
 5067     (write _test-input-stream "fn foo {\n")
 5068     (write _test-input-stream "  var a: (array int 3)\n")
 5069     (write _test-input-stream "  var b/eax: int <- length a\n")
 5070     (write _test-input-stream "}\n")
 5071     # convert
 5072     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5073     (flush _test-output-buffered-file)
 5074 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5080     # check output
 5081     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 5082     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 5083     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 5084     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 5085     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 5086     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 5087     # define x
 5088     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 5089     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 5090     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 5091     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 5092     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 5093     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 5094     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 5095     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 5096     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 5097     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 5098     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 5099     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 5100     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 5101     # . epilogue
 5102     89/<- %esp 5/r32/ebp
 5103     5d/pop-to-ebp
 5104     c3/return
 5105 
 5106 test-reg-var-def-with-read-of-same-register:
 5107     # . prologue
 5108     55/push-ebp
 5109     89/<- %ebp 4/r32/esp
 5110     # setup
 5111     (clear-stream _test-input-stream)
 5112     (clear-stream $_test-input-buffered-file->buffer)
 5113     (clear-stream _test-output-stream)
 5114     (clear-stream $_test-output-buffered-file->buffer)
 5115     (clear-stream _test-error-stream)
 5116     (clear-stream $_test-error-buffered-file->buffer)
 5117     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 5118     68/push 0/imm32
 5119     68/push 0/imm32
 5120     89/<- %edx 4/r32/esp
 5121     (tailor-exit-descriptor %edx 0x10)
 5122     #
 5123     (write _test-input-stream "fn foo {\n")
 5124     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5125     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5126     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5127     (write _test-input-stream "}\n")
 5128     # convert
 5129     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5130     # registers except esp could be clobbered at this point (though they shouldn't be)
 5131     # restore ed
 5132     89/<- %edx 4/r32/esp
 5133     (flush _test-output-buffered-file)
 5134     (flush _test-error-buffered-file)
 5135 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5141 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5147     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 5148     # check output
 5149     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 5150     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 5151     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 5152     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 5153     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 5154     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 5155     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 5156     (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")
 5157     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-reg-var-def-with-read-of-same-register/8")
 5158     (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")
 5159     (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")
 5160     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-reg-var-def-with-read-of-same-register/13")
 5161     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/14")
 5162     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/15")
 5163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/16")
 5164     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/17")
 5165     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/18")
 5166     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/19")
 5167     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/20")
 5168     # don't restore from ebp
 5169     81 0/subop/add %esp 8/imm32
 5170     # . epilogue
 5171     5d/pop-to-ebp
 5172     c3/return
 5173 
 5174 test-convert-index-into-array:
 5175     # . prologue
 5176     55/push-ebp
 5177     89/<- %ebp 4/r32/esp
 5178     # setup
 5179     (clear-stream _test-input-stream)
 5180     (clear-stream $_test-input-buffered-file->buffer)
 5181     (clear-stream _test-output-stream)
 5182     (clear-stream $_test-output-buffered-file->buffer)
 5183     #
 5184     (write _test-input-stream "fn foo {\n")
 5185     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5186     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5187     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5188     (write _test-input-stream "}\n")
 5189     # convert
 5190     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5191     (flush _test-output-buffered-file)
 5192 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5198     # check output
 5199     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 5200     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 5201     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 5202     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 5203     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 5204     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 5205     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 5206     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 5207     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 5208     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 5209     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/10")
 5210     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/11")
 5211     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/12")
 5212     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/13")
 5213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/14")
 5214     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/15")
 5215     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/16")
 5216     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/17")
 5217     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/18")
 5218     # . epilogue
 5219     89/<- %esp 5/r32/ebp
 5220     5d/pop-to-ebp
 5221     c3/return
 5222 
 5223 test-convert-index-into-array-of-bytes:
 5224     # . prologue
 5225     55/push-ebp
 5226     89/<- %ebp 4/r32/esp
 5227     # setup
 5228     (clear-stream _test-input-stream)
 5229     (clear-stream $_test-input-buffered-file->buffer)
 5230     (clear-stream _test-output-stream)
 5231     (clear-stream $_test-output-buffered-file->buffer)
 5232     #
 5233     (write _test-input-stream "fn foo {\n")
 5234     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5235     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5236     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 5237     (write _test-input-stream "}\n")
 5238     # convert
 5239     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5240     (flush _test-output-buffered-file)
 5241 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5247     # check output
 5248     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 5249     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 5250     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 5251     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 5252     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 5253     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 5254     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 5255     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 5256     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 5257     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 5258     (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")
 5259     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/13")
 5260     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/14")
 5261     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/15")
 5262     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/16")
 5263     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/17")
 5264     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/18")
 5265     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/19")
 5266     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/20")
 5267     # . epilogue
 5268     89/<- %esp 5/r32/ebp
 5269     5d/pop-to-ebp
 5270     c3/return
 5271 
 5272 test-convert-index-into-array-with-literal:
 5273     # . prologue
 5274     55/push-ebp
 5275     89/<- %ebp 4/r32/esp
 5276     # setup
 5277     (clear-stream _test-input-stream)
 5278     (clear-stream $_test-input-buffered-file->buffer)
 5279     (clear-stream _test-output-stream)
 5280     (clear-stream $_test-output-buffered-file->buffer)
 5281     #
 5282     (write _test-input-stream "fn foo {\n")
 5283     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5284     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 5285     (write _test-input-stream "}\n")
 5286     # convert
 5287     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5288     (flush _test-output-buffered-file)
 5289 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5295     # check output
 5296     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 5297     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 5298     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 5299     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 5300     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 5301     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 5302     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 5303     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 5304                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 5305     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/8")
 5306     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/9")
 5307     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/10")
 5308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/11")
 5309     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/12")
 5310     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/13")
 5311     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/14")
 5312     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/15")
 5313     # . epilogue
 5314     89/<- %esp 5/r32/ebp
 5315     5d/pop-to-ebp
 5316     c3/return
 5317 
 5318 test-convert-index-into-array-of-bytes-with-literal:
 5319     # . prologue
 5320     55/push-ebp
 5321     89/<- %ebp 4/r32/esp
 5322     # setup
 5323     (clear-stream _test-input-stream)
 5324     (clear-stream $_test-input-buffered-file->buffer)
 5325     (clear-stream _test-output-stream)
 5326     (clear-stream $_test-output-buffered-file->buffer)
 5327     #
 5328     (write _test-input-stream "fn foo {\n")
 5329     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5330     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 5331     (write _test-input-stream "}\n")
 5332     # convert
 5333     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5334     (flush _test-output-buffered-file)
 5335 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5341     # check output
 5342     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 5343     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 5344     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 5345     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 5346     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 5347     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 5348     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 5349     (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")
 5350                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 5351     (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")
 5352     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 5353     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 5354     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 5355     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 5356     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 5357     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 5358     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 5359     # . epilogue
 5360     89/<- %esp 5/r32/ebp
 5361     5d/pop-to-ebp
 5362     c3/return
 5363 
 5364 test-convert-index-into-array-on-stack:
 5365     # . prologue
 5366     55/push-ebp
 5367     89/<- %ebp 4/r32/esp
 5368     # setup
 5369     (clear-stream _test-input-stream)
 5370     (clear-stream $_test-input-buffered-file->buffer)
 5371     (clear-stream _test-output-stream)
 5372     (clear-stream $_test-output-buffered-file->buffer)
 5373     #
 5374     (write _test-input-stream "fn foo {\n")
 5375     (write _test-input-stream "  var arr: (array int 3)\n")
 5376     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 5377     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5378     (write _test-input-stream "}\n")
 5379     # convert
 5380     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5381     (flush _test-output-buffered-file)
 5382 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5388     # check output
 5389     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 5390     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 5391     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 5392     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 5393     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 5394     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 5395     # var arr
 5396     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 5397     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 5398     # var idx
 5399     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 5400     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 5401     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 5402     (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")
 5403     # reclaim idx
 5404     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/11")
 5405     # reclaim arr
 5406     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/12")
 5407     #
 5408     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/13")
 5409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/14")
 5410     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/15")
 5411     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/16")
 5412     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/17")
 5413     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/18")
 5414     # . epilogue
 5415     89/<- %esp 5/r32/ebp
 5416     5d/pop-to-ebp
 5417     c3/return
 5418 
 5419 test-convert-index-into-array-on-stack-with-literal:
 5420     # . prologue
 5421     55/push-ebp
 5422     89/<- %ebp 4/r32/esp
 5423     # setup
 5424     (clear-stream _test-input-stream)
 5425     (clear-stream $_test-input-buffered-file->buffer)
 5426     (clear-stream _test-output-stream)
 5427     (clear-stream $_test-output-buffered-file->buffer)
 5428     #
 5429     (write _test-input-stream "fn foo {\n")
 5430     (write _test-input-stream "  var arr: (array int 3)\n")
 5431     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 5432     (write _test-input-stream "}\n")
 5433     # convert
 5434     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5435     (flush _test-output-buffered-file)
 5436 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5442     # check output
 5443     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 5444     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 5445     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 5446     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 5447     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 5448     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 5449     # var arr
 5450     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 5451     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 5452     # var x
 5453     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 5454     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 5455     (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")
 5456     # reclaim x
 5457     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/10")
 5458     # reclaim arr
 5459     (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")
 5460     #
 5461     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/12")
 5462     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/13")
 5463     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/14")
 5464     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/15")
 5465     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/16")
 5466     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/17")
 5467     # . epilogue
 5468     89/<- %esp 5/r32/ebp
 5469     5d/pop-to-ebp
 5470     c3/return
 5471 
 5472 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 5473     # . prologue
 5474     55/push-ebp
 5475     89/<- %ebp 4/r32/esp
 5476     # setup
 5477     (clear-stream _test-input-stream)
 5478     (clear-stream $_test-input-buffered-file->buffer)
 5479     (clear-stream _test-output-stream)
 5480     (clear-stream $_test-output-buffered-file->buffer)
 5481     #
 5482     (write _test-input-stream "fn foo {\n")
 5483     (write _test-input-stream "  var arr: (array byte 3)\n")
 5484     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 5485     (write _test-input-stream "}\n")
 5486     # convert
 5487     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5488     (flush _test-output-buffered-file)
 5489 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5495     # check output
 5496     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 5497     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 5498     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 5499     (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")
 5500     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 5501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 5502     # var arr
 5503     (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")
 5504     (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")
 5505     # var x
 5506     (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")
 5507     # x is at (ebp-7) + 4 + 2 = ebp-1
 5508     (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")
 5509     # reclaim x
 5510     (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")
 5511     # reclaim arr
 5512     (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")
 5513     #
 5514     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 5515     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 5516     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 5517     (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")
 5518     (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")
 5519     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 5520     # . epilogue
 5521     89/<- %esp 5/r32/ebp
 5522     5d/pop-to-ebp
 5523     c3/return
 5524 
 5525 test-convert-index-into-array-using-offset:
 5526     # . prologue
 5527     55/push-ebp
 5528     89/<- %ebp 4/r32/esp
 5529     # setup
 5530     (clear-stream _test-input-stream)
 5531     (clear-stream $_test-input-buffered-file->buffer)
 5532     (clear-stream _test-output-stream)
 5533     (clear-stream $_test-output-buffered-file->buffer)
 5534     #
 5535     (write _test-input-stream "fn foo {\n")
 5536     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5537     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5538     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5539     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5540     (write _test-input-stream "}\n")
 5541     # convert
 5542     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5543     (flush _test-output-buffered-file)
 5544 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5550     # check output
 5551     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 5552     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 5553     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 5554     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 5555     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 5556     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 5557     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 5558     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 5559     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 5560     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 5561     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 5562     (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")
 5563     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/12")
 5564     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/13")
 5565     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/14")
 5566     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/15")
 5567     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/16")
 5568     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/17")
 5569     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/18")
 5570     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/19")
 5571     # . epilogue
 5572     89/<- %esp 5/r32/ebp
 5573     5d/pop-to-ebp
 5574     c3/return
 5575 
 5576 test-convert-index-into-array-of-bytes-using-offset:
 5577     # . prologue
 5578     55/push-ebp
 5579     89/<- %ebp 4/r32/esp
 5580     # setup
 5581     (clear-stream _test-input-stream)
 5582     (clear-stream $_test-input-buffered-file->buffer)
 5583     (clear-stream _test-output-stream)
 5584     (clear-stream $_test-output-buffered-file->buffer)
 5585     #
 5586     (write _test-input-stream "fn foo {\n")
 5587     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5588     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5589     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5590     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5591     (write _test-input-stream "}\n")
 5592     # convert
 5593     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5594     (flush _test-output-buffered-file)
 5595 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5601     # check output
 5602     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 5603     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 5604     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 5605     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 5606     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 5607     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 5608     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 5609     (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")
 5610     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 5611     (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")
 5612     (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")
 5613     (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")
 5614     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/12")
 5615     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 5616     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/14")
 5617     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/15")
 5618     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/16")
 5619     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/17")
 5620     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/18")
 5621     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/19")
 5622     # . epilogue
 5623     89/<- %esp 5/r32/ebp
 5624     5d/pop-to-ebp
 5625     c3/return
 5626 
 5627 test-convert-index-into-array-using-offset-on-stack:
 5628     # . prologue
 5629     55/push-ebp
 5630     89/<- %ebp 4/r32/esp
 5631     # setup
 5632     (clear-stream _test-input-stream)
 5633     (clear-stream $_test-input-buffered-file->buffer)
 5634     (clear-stream _test-output-stream)
 5635     (clear-stream $_test-output-buffered-file->buffer)
 5636     #
 5637     (write _test-input-stream "fn foo {\n")
 5638     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5639     (write _test-input-stream "  var idx: int\n")
 5640     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5641     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5642     (write _test-input-stream "}\n")
 5643     # convert
 5644     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5645     (flush _test-output-buffered-file)
 5646 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5652     # check output
 5653     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 5654     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 5655     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 5656     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 5657     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 5658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 5659     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 5660     (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")
 5661     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 5662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 5663     (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")
 5664     (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")
 5665     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/12")
 5666     (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")
 5667     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/14")
 5668     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/15")
 5669     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/16")
 5670     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/17")
 5671     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/18")
 5672     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/19")
 5673     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/20")
 5674     # . epilogue
 5675     89/<- %esp 5/r32/ebp
 5676     5d/pop-to-ebp
 5677     c3/return
 5678 
 5679 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 5680     # . prologue
 5681     55/push-ebp
 5682     89/<- %ebp 4/r32/esp
 5683     # setup
 5684     (clear-stream _test-input-stream)
 5685     (clear-stream $_test-input-buffered-file->buffer)
 5686     (clear-stream _test-output-stream)
 5687     (clear-stream $_test-output-buffered-file->buffer)
 5688     #
 5689     (write _test-input-stream "fn foo {\n")
 5690     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5691     (write _test-input-stream "  var idx: int\n")
 5692     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5693     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5694     (write _test-input-stream "}\n")
 5695     # convert
 5696     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5697     (flush _test-output-buffered-file)
 5698 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5704     # check output
 5705     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 5706     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 5707     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 5708     (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")
 5709     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 5710     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 5711     (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")
 5712     (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")
 5713     (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")
 5714     (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")
 5715     (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")
 5716     (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")
 5717     (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")
 5718     (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")
 5719     (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")
 5720     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 5721     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 5722     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 5723     (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")
 5724     (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")
 5725     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 5726     # . epilogue
 5727     89/<- %esp 5/r32/ebp
 5728     5d/pop-to-ebp
 5729     c3/return
 5730 
 5731 test-convert-function-and-type-definition:
 5732     # . prologue
 5733     55/push-ebp
 5734     89/<- %ebp 4/r32/esp
 5735     # setup
 5736     (clear-stream _test-input-stream)
 5737     (clear-stream $_test-input-buffered-file->buffer)
 5738     (clear-stream _test-output-stream)
 5739     (clear-stream $_test-output-buffered-file->buffer)
 5740     #
 5741     (write _test-input-stream "fn foo a: (addr t) {\n")
 5742     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 5743     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 5744     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 5745     (write _test-input-stream "}\n")
 5746     (write _test-input-stream "type t {\n")
 5747     (write _test-input-stream "  x: int\n")
 5748     (write _test-input-stream "  y: int\n")
 5749     (write _test-input-stream "}\n")
 5750     # convert
 5751     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5752     (flush _test-output-buffered-file)
 5753 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5759     # check output
 5760     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 5761     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 5762     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 5763     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 5764     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 5765     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 5766     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 5767     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 5768     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 5769     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 5770     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 5771     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 5772     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 5773     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 5774     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 5775     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 5776     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 5777     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 5778     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 5779     # . epilogue
 5780     89/<- %esp 5/r32/ebp
 5781     5d/pop-to-ebp
 5782     c3/return
 5783 
 5784 test-type-definition-with-array:
 5785     # . prologue
 5786     55/push-ebp
 5787     89/<- %ebp 4/r32/esp
 5788     # setup
 5789     (clear-stream _test-input-stream)
 5790     (clear-stream $_test-input-buffered-file->buffer)
 5791     (clear-stream _test-output-stream)
 5792     (clear-stream $_test-output-buffered-file->buffer)
 5793     (clear-stream _test-error-stream)
 5794     (clear-stream $_test-error-buffered-file->buffer)
 5795     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5796     68/push 0/imm32
 5797     68/push 0/imm32
 5798     89/<- %edx 4/r32/esp
 5799     (tailor-exit-descriptor %edx 0x10)
 5800     #
 5801     (write _test-input-stream "type t {\n")
 5802     (write _test-input-stream "  a: (array int 3)\n")
 5803     (write _test-input-stream "}\n")
 5804     # convert
 5805     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5806     # registers except esp clobbered at this point
 5807     # restore ed
 5808     89/<- %edx 4/r32/esp
 5809     (flush _test-output-buffered-file)
 5810     (flush _test-error-buffered-file)
 5811 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5817     # check output
 5818     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 5819     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 5820     # check that stop(1) was called
 5821     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 5822     # don't restore from ebp
 5823     81 0/subop/add %esp 8/imm32
 5824     # . epilogue
 5825     5d/pop-to-ebp
 5826     c3/return
 5827 
 5828 test-type-definition-with-addr:
 5829     # . prologue
 5830     55/push-ebp
 5831     89/<- %ebp 4/r32/esp
 5832     # setup
 5833     (clear-stream _test-input-stream)
 5834     (clear-stream $_test-input-buffered-file->buffer)
 5835     (clear-stream _test-output-stream)
 5836     (clear-stream $_test-output-buffered-file->buffer)
 5837     (clear-stream _test-error-stream)
 5838     (clear-stream $_test-error-buffered-file->buffer)
 5839     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5840     68/push 0/imm32
 5841     68/push 0/imm32
 5842     89/<- %edx 4/r32/esp
 5843     (tailor-exit-descriptor %edx 0x10)
 5844     #
 5845     (write _test-input-stream "type t {\n")
 5846     (write _test-input-stream "  a: (addr int)\n")
 5847     (write _test-input-stream "}\n")
 5848     # convert
 5849     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5850     # registers except esp clobbered at this point
 5851     # restore ed
 5852     89/<- %edx 4/r32/esp
 5853     (flush _test-output-buffered-file)
 5854     (flush _test-error-buffered-file)
 5855 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5861     # check output
 5862     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 5863     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 5864     # check that stop(1) was called
 5865     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 5866     # don't restore from ebp
 5867     81 0/subop/add %esp 8/imm32
 5868     # . epilogue
 5869     5d/pop-to-ebp
 5870     c3/return
 5871 
 5872 test-convert-function-with-local-var-with-user-defined-type:
 5873     # . prologue
 5874     55/push-ebp
 5875     89/<- %ebp 4/r32/esp
 5876     # setup
 5877     (clear-stream _test-input-stream)
 5878     (clear-stream $_test-input-buffered-file->buffer)
 5879     (clear-stream _test-output-stream)
 5880     (clear-stream $_test-output-buffered-file->buffer)
 5881     #
 5882     (write _test-input-stream "fn foo {\n")
 5883     (write _test-input-stream "  var a: t\n")
 5884     (write _test-input-stream "}\n")
 5885     (write _test-input-stream "type t {\n")
 5886     (write _test-input-stream "  x: int\n")
 5887     (write _test-input-stream "  y: int\n")
 5888     (write _test-input-stream "}\n")
 5889     # convert
 5890     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5891     (flush _test-output-buffered-file)
 5892 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5898     # check output
 5899     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 5900     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 5901     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 5902     (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")
 5903     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 5904     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 5905     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 5906     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 5907     (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")
 5908     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 5909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 5910     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 5911     (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")
 5912     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 5913     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 5914     # . epilogue
 5915     89/<- %esp 5/r32/ebp
 5916     5d/pop-to-ebp
 5917     c3/return
 5918 
 5919 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 5920     # . prologue
 5921     55/push-ebp
 5922     89/<- %ebp 4/r32/esp
 5923     # setup
 5924     (clear-stream _test-input-stream)
 5925     (clear-stream $_test-input-buffered-file->buffer)
 5926     (clear-stream _test-output-stream)
 5927     (clear-stream $_test-output-buffered-file->buffer)
 5928     #
 5929     (write _test-input-stream "fn foo {\n")
 5930     (write _test-input-stream "  var a: t\n")
 5931     (write _test-input-stream "}\n")
 5932     (write _test-input-stream "type t {\n")
 5933     (write _test-input-stream "  x: s\n")
 5934     (write _test-input-stream "}\n")
 5935     (write _test-input-stream "type s {\n")
 5936     (write _test-input-stream "  z: int\n")
 5937     (write _test-input-stream "}\n")
 5938     # convert
 5939     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5940     (flush _test-output-buffered-file)
 5941 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5947     # check output
 5948     (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")
 5949     (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")
 5950     (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")
 5951     (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")
 5952     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 5953     (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")
 5954     (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")
 5955     (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")
 5956     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 5957     (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")
 5958     (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")
 5959     (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")
 5960     (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")
 5961     (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")
 5962     # . epilogue
 5963     89/<- %esp 5/r32/ebp
 5964     5d/pop-to-ebp
 5965     c3/return
 5966 
 5967 test-convert-function-call-with-arg-of-user-defined-type:
 5968     # . prologue
 5969     55/push-ebp
 5970     89/<- %ebp 4/r32/esp
 5971     # setup
 5972     (clear-stream _test-input-stream)
 5973     (clear-stream $_test-input-buffered-file->buffer)
 5974     (clear-stream _test-output-stream)
 5975     (clear-stream $_test-output-buffered-file->buffer)
 5976     #
 5977     (write _test-input-stream "fn f {\n")
 5978     (write _test-input-stream "  var a: t\n")
 5979     (write _test-input-stream "  foo a\n")
 5980     (write _test-input-stream "}\n")
 5981     (write _test-input-stream "fn foo x: t {\n")
 5982     (write _test-input-stream "}\n")
 5983     (write _test-input-stream "type t {\n")
 5984     (write _test-input-stream "  x: int\n")
 5985     (write _test-input-stream "  y: int\n")
 5986     (write _test-input-stream "}\n")
 5987     # convert
 5988     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5989     (flush _test-output-buffered-file)
 5990 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5996     # check output
 5997     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5998     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5999     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6000     (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")
 6001     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6002     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6003     # var a: t
 6004     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6005     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6006     # foo a
 6007     (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")
 6008     #
 6009     (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")
 6010     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6011     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6012     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6013     (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")
 6014     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6015     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6016     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6017     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6018     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6019     (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")
 6020     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6021     (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")
 6022     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6023     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6024     # . epilogue
 6025     89/<- %esp 5/r32/ebp
 6026     5d/pop-to-ebp
 6027     c3/return
 6028 
 6029 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 6030     # . prologue
 6031     55/push-ebp
 6032     89/<- %ebp 4/r32/esp
 6033     # setup
 6034     (clear-stream _test-input-stream)
 6035     (clear-stream $_test-input-buffered-file->buffer)
 6036     (clear-stream _test-output-stream)
 6037     (clear-stream $_test-output-buffered-file->buffer)
 6038     #
 6039     (write _test-input-stream "fn f {\n")
 6040     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 6041     (write _test-input-stream "  foo *a\n")
 6042     (write _test-input-stream "}\n")
 6043     (write _test-input-stream "fn foo x: t {\n")
 6044     (write _test-input-stream "}\n")
 6045     (write _test-input-stream "type t {\n")
 6046     (write _test-input-stream "  x: int\n")
 6047     (write _test-input-stream "  y: int\n")
 6048     (write _test-input-stream "}\n")
 6049     # convert
 6050     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6051     (flush _test-output-buffered-file)
 6052 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6058     # check output
 6059     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6060     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6061     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6062     (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")
 6063     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6064     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6065     # var a
 6066     (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")
 6067     (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")
 6068     # foo a
 6069     (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")
 6070     #
 6071     (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")
 6072     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6073     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6074     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6075     (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")
 6076     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6077     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6078     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6079     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6080     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6081     (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")
 6082     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6083     (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")
 6084     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6085     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6086     # . epilogue
 6087     89/<- %esp 5/r32/ebp
 6088     5d/pop-to-ebp
 6089     c3/return
 6090 
 6091 # we don't have special support for call-by-reference; just explicitly create
 6092 # a new variable with the address of the arg
 6093 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 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     #
 6103     (write _test-input-stream "fn f {\n")
 6104     (write _test-input-stream "  var a: t\n")
 6105     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 6106     (write _test-input-stream "  foo b\n")
 6107     (write _test-input-stream "}\n")
 6108     (write _test-input-stream "fn foo x: (addr t) {\n")
 6109     (write _test-input-stream "  var x/ecx: (addr int) <- copy x\n")
 6110     (write _test-input-stream "  increment *x\n")
 6111     (write _test-input-stream "}\n")
 6112     (write _test-input-stream "type t {\n")
 6113     (write _test-input-stream "  x: int\n")
 6114     (write _test-input-stream "  y: int\n")
 6115     (write _test-input-stream "}\n")
 6116     # convert
 6117     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6118     (flush _test-output-buffered-file)
 6119 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6125     # check output
 6126     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 6127     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 6128     (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")
 6129     (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")
 6130     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 6131     (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")
 6132     # var a: t
 6133     (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")
 6134     (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")
 6135     # var b/eax: (addr t)
 6136     (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")
 6137     (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")
 6138     # foo a
 6139     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 6140     #
 6141     (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")
 6142     (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")
 6143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 6144     (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")
 6145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 6146     (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")
 6147     (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")
 6148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 6149     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 6150     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 6151     (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")
 6152     (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")
 6153     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 6154     (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")
 6155     (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")
 6156     (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")
 6157     (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")
 6158     (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")
 6159     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 6160     (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")
 6161     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 6162     (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")
 6163     (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")
 6164     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/34")
 6165     # . epilogue
 6166     89/<- %esp 5/r32/ebp
 6167     5d/pop-to-ebp
 6168     c3/return
 6169 
 6170 test-convert-get-on-local-variable:
 6171     # . prologue
 6172     55/push-ebp
 6173     89/<- %ebp 4/r32/esp
 6174     # setup
 6175     (clear-stream _test-input-stream)
 6176     (clear-stream $_test-input-buffered-file->buffer)
 6177     (clear-stream _test-output-stream)
 6178     (clear-stream $_test-output-buffered-file->buffer)
 6179     #
 6180     (write _test-input-stream "fn foo {\n")
 6181     (write _test-input-stream "  var a: t\n")
 6182     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6183     (write _test-input-stream "}\n")
 6184     (write _test-input-stream "type t {\n")
 6185     (write _test-input-stream "  x: int\n")
 6186     (write _test-input-stream "  y: int\n")
 6187     (write _test-input-stream "}\n")
 6188     # convert
 6189     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6190     (flush _test-output-buffered-file)
 6191 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6197     # check output
 6198     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 6199     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 6200     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 6201     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 6202     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 6203     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 6204     # var a
 6205     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 6206     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 6207     # var c
 6208     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 6209     # get
 6210     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 6211     # reclaim c
 6212     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 6213     # reclaim a
 6214     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 6215     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 6216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 6217     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 6218     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 6219     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 6220     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 6221     # . epilogue
 6222     89/<- %esp 5/r32/ebp
 6223     5d/pop-to-ebp
 6224     c3/return
 6225 
 6226 test-convert-get-on-function-argument:
 6227     # . prologue
 6228     55/push-ebp
 6229     89/<- %ebp 4/r32/esp
 6230     # setup
 6231     (clear-stream _test-input-stream)
 6232     (clear-stream $_test-input-buffered-file->buffer)
 6233     (clear-stream _test-output-stream)
 6234     (clear-stream $_test-output-buffered-file->buffer)
 6235     #
 6236     (write _test-input-stream "fn foo a: t {\n")
 6237     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6238     (write _test-input-stream "}\n")
 6239     (write _test-input-stream "type t {\n")
 6240     (write _test-input-stream "  x: int\n")
 6241     (write _test-input-stream "  y: int\n")
 6242     (write _test-input-stream "}\n")
 6243     # convert
 6244     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6245     (flush _test-output-buffered-file)
 6246 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6252     # check output
 6253     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 6254     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 6255     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 6256     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 6257     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 6258     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 6259     # var c
 6260     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 6261     # get
 6262     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 6263     # reclaim c
 6264     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 6265     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 6266     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 6267     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 6268     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 6269     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 6270     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 6271     # . epilogue
 6272     89/<- %esp 5/r32/ebp
 6273     5d/pop-to-ebp
 6274     c3/return
 6275 
 6276 test-convert-get-on-function-argument-with-known-type:
 6277     # . prologue
 6278     55/push-ebp
 6279     89/<- %ebp 4/r32/esp
 6280     # setup
 6281     (clear-stream _test-input-stream)
 6282     (clear-stream $_test-input-buffered-file->buffer)
 6283     (clear-stream _test-output-stream)
 6284     (clear-stream $_test-output-buffered-file->buffer)
 6285     #
 6286     (write _test-input-stream "type t {\n")
 6287     (write _test-input-stream "  x: int\n")
 6288     (write _test-input-stream "  y: int\n")
 6289     (write _test-input-stream "}\n")
 6290     (write _test-input-stream "fn foo a: t {\n")
 6291     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6292     (write _test-input-stream "}\n")
 6293     # convert
 6294     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6295     (flush _test-output-buffered-file)
 6296 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6302     # check output
 6303     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 6304     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 6305     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 6306     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 6307     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 6308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 6309     # var c
 6310     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 6311     # get
 6312     (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")
 6313     # reclaim c
 6314     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 6315     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 6316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 6317     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 6318     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 6319     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 6320     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 6321     # . epilogue
 6322     89/<- %esp 5/r32/ebp
 6323     5d/pop-to-ebp
 6324     c3/return
 6325 
 6326 test-add-with-too-many-inouts:
 6327     # . prologue
 6328     55/push-ebp
 6329     89/<- %ebp 4/r32/esp
 6330     # setup
 6331     (clear-stream _test-input-stream)
 6332     (clear-stream $_test-input-buffered-file->buffer)
 6333     (clear-stream _test-output-stream)
 6334     (clear-stream $_test-output-buffered-file->buffer)
 6335     (clear-stream _test-error-stream)
 6336     (clear-stream $_test-error-buffered-file->buffer)
 6337     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6338     68/push 0/imm32
 6339     68/push 0/imm32
 6340     89/<- %edx 4/r32/esp
 6341     (tailor-exit-descriptor %edx 0x10)
 6342     #
 6343     (write _test-input-stream "fn foo {\n")
 6344     (write _test-input-stream "  var a: int\n")
 6345     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 6346     (write _test-input-stream "}\n")
 6347     # convert
 6348     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6349     # registers except esp clobbered at this point
 6350     # restore ed
 6351     89/<- %edx 4/r32/esp
 6352     (flush _test-output-buffered-file)
 6353     (flush _test-error-buffered-file)
 6354 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6360     # check output
 6361     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 6362     (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")
 6363     # check that stop(1) was called
 6364     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 6365     # don't restore from ebp
 6366     81 0/subop/add %esp 8/imm32
 6367     # . epilogue
 6368     5d/pop-to-ebp
 6369     c3/return
 6370 
 6371 test-add-with-too-many-inouts-2:
 6372     # . prologue
 6373     55/push-ebp
 6374     89/<- %ebp 4/r32/esp
 6375     # setup
 6376     (clear-stream _test-input-stream)
 6377     (clear-stream $_test-input-buffered-file->buffer)
 6378     (clear-stream _test-output-stream)
 6379     (clear-stream $_test-output-buffered-file->buffer)
 6380     (clear-stream _test-error-stream)
 6381     (clear-stream $_test-error-buffered-file->buffer)
 6382     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6383     68/push 0/imm32
 6384     68/push 0/imm32
 6385     89/<- %edx 4/r32/esp
 6386     (tailor-exit-descriptor %edx 0x10)
 6387     #
 6388     (write _test-input-stream "fn foo {\n")
 6389     (write _test-input-stream "  var a: int\n")
 6390     (write _test-input-stream "  add-to a, 0, 1\n")
 6391     (write _test-input-stream "}\n")
 6392     # convert
 6393     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6394     # registers except esp clobbered at this point
 6395     # restore ed
 6396     89/<- %edx 4/r32/esp
 6397     (flush _test-output-buffered-file)
 6398     (flush _test-error-buffered-file)
 6399 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6405     # check output
 6406     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 6407     (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")
 6408     # check that stop(1) was called
 6409     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 6410     # don't restore from ebp
 6411     81 0/subop/add %esp 8/imm32
 6412     # . epilogue
 6413     5d/pop-to-ebp
 6414     c3/return
 6415 
 6416 test-add-with-too-many-outputs:
 6417     # . prologue
 6418     55/push-ebp
 6419     89/<- %ebp 4/r32/esp
 6420     # setup
 6421     (clear-stream _test-input-stream)
 6422     (clear-stream $_test-input-buffered-file->buffer)
 6423     (clear-stream _test-output-stream)
 6424     (clear-stream $_test-output-buffered-file->buffer)
 6425     (clear-stream _test-error-stream)
 6426     (clear-stream $_test-error-buffered-file->buffer)
 6427     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6428     68/push 0/imm32
 6429     68/push 0/imm32
 6430     89/<- %edx 4/r32/esp
 6431     (tailor-exit-descriptor %edx 0x10)
 6432     #
 6433     (write _test-input-stream "fn foo {\n")
 6434     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 6435     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 6436     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 6437     (write _test-input-stream "  c, b <- add a\n")
 6438     (write _test-input-stream "}\n")
 6439     # convert
 6440     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6441     # registers except esp clobbered at this point
 6442     # restore ed
 6443     89/<- %edx 4/r32/esp
 6444     (flush _test-output-buffered-file)
 6445     (flush _test-error-buffered-file)
 6446 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6452     # check output
 6453     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 6454     (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")
 6455     # check that stop(1) was called
 6456     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 6457     # don't restore from ebp
 6458     81 0/subop/add %esp 8/imm32
 6459     # . epilogue
 6460     5d/pop-to-ebp
 6461     c3/return
 6462 
 6463 test-add-with-non-number:
 6464     # . prologue
 6465     55/push-ebp
 6466     89/<- %ebp 4/r32/esp
 6467     # setup
 6468     (clear-stream _test-input-stream)
 6469     (clear-stream $_test-input-buffered-file->buffer)
 6470     (clear-stream _test-output-stream)
 6471     (clear-stream $_test-output-buffered-file->buffer)
 6472     (clear-stream _test-error-stream)
 6473     (clear-stream $_test-error-buffered-file->buffer)
 6474     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6475     68/push 0/imm32
 6476     68/push 0/imm32
 6477     89/<- %edx 4/r32/esp
 6478     (tailor-exit-descriptor %edx 0x10)
 6479     #
 6480     (write _test-input-stream "fn foo {\n")
 6481     (write _test-input-stream "  var a: int\n")
 6482     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 6483     (write _test-input-stream "}\n")
 6484     # convert
 6485     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6486     # registers except esp clobbered at this point
 6487     # restore ed
 6488     89/<- %edx 4/r32/esp
 6489     (flush _test-output-buffered-file)
 6490     (flush _test-error-buffered-file)
 6491 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6497     # check output
 6498     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 6499     (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")
 6500     # check that stop(1) was called
 6501     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 6502     # don't restore from ebp
 6503     81 0/subop/add %esp 8/imm32
 6504     # . epilogue
 6505     5d/pop-to-ebp
 6506     c3/return
 6507 
 6508 test-add-with-addr-dereferenced:
 6509     # . prologue
 6510     55/push-ebp
 6511     89/<- %ebp 4/r32/esp
 6512     # setup
 6513     (clear-stream _test-input-stream)
 6514     (clear-stream $_test-input-buffered-file->buffer)
 6515     (clear-stream _test-output-stream)
 6516     (clear-stream $_test-output-buffered-file->buffer)
 6517     #
 6518     (write _test-input-stream "fn foo {\n")
 6519     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 6520     (write _test-input-stream "  add-to *a, 1\n")
 6521     (write _test-input-stream "}\n")
 6522     # convert
 6523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6524     (flush _test-output-buffered-file)
 6525     # no error
 6526     # . epilogue
 6527     89/<- %esp 5/r32/ebp
 6528     5d/pop-to-ebp
 6529     c3/return
 6530 
 6531 test-get-with-wrong-field:
 6532     # . prologue
 6533     55/push-ebp
 6534     89/<- %ebp 4/r32/esp
 6535     # setup
 6536     (clear-stream _test-input-stream)
 6537     (clear-stream $_test-input-buffered-file->buffer)
 6538     (clear-stream _test-output-stream)
 6539     (clear-stream $_test-output-buffered-file->buffer)
 6540     (clear-stream _test-error-stream)
 6541     (clear-stream $_test-error-buffered-file->buffer)
 6542     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6543     68/push 0/imm32
 6544     68/push 0/imm32
 6545     89/<- %edx 4/r32/esp
 6546     (tailor-exit-descriptor %edx 0x10)
 6547     #
 6548     (write _test-input-stream "fn foo {\n")
 6549     (write _test-input-stream "  var a: t\n")
 6550     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6551     (write _test-input-stream "}\n")
 6552     (write _test-input-stream "type t {\n")
 6553     (write _test-input-stream "  x: int\n")
 6554     (write _test-input-stream "}\n")
 6555     # convert
 6556     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6557     # registers except esp clobbered at this point
 6558     # restore ed
 6559     89/<- %edx 4/r32/esp
 6560     (flush _test-output-buffered-file)
 6561     (flush _test-error-buffered-file)
 6562 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6568     # check output
 6569     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 6570     (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")
 6571     # check that stop(1) was called
 6572     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 6573     # don't restore from ebp
 6574     81 0/subop/add %esp 8/imm32
 6575     # . epilogue
 6576     5d/pop-to-ebp
 6577     c3/return
 6578 
 6579 test-get-with-wrong-base-type:
 6580     # . prologue
 6581     55/push-ebp
 6582     89/<- %ebp 4/r32/esp
 6583     # setup
 6584     (clear-stream _test-input-stream)
 6585     (clear-stream $_test-input-buffered-file->buffer)
 6586     (clear-stream _test-output-stream)
 6587     (clear-stream $_test-output-buffered-file->buffer)
 6588     (clear-stream _test-error-stream)
 6589     (clear-stream $_test-error-buffered-file->buffer)
 6590     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6591     68/push 0/imm32
 6592     68/push 0/imm32
 6593     89/<- %edx 4/r32/esp
 6594     (tailor-exit-descriptor %edx 0x10)
 6595     #
 6596     (write _test-input-stream "fn foo {\n")
 6597     (write _test-input-stream "  var a: int\n")
 6598     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6599     (write _test-input-stream "}\n")
 6600     # convert
 6601     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6602     # registers except esp clobbered at this point
 6603     # restore ed
 6604     89/<- %edx 4/r32/esp
 6605     (flush _test-output-buffered-file)
 6606     (flush _test-error-buffered-file)
 6607 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6613     # check output
 6614     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 6615     (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")
 6616     # check that stop(1) was called
 6617     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 6618     # don't restore from ebp
 6619     81 0/subop/add %esp 8/imm32
 6620     # . epilogue
 6621     5d/pop-to-ebp
 6622     c3/return
 6623 
 6624 test-get-with-wrong-base-type-2:
 6625     # . prologue
 6626     55/push-ebp
 6627     89/<- %ebp 4/r32/esp
 6628     # setup
 6629     (clear-stream _test-input-stream)
 6630     (clear-stream $_test-input-buffered-file->buffer)
 6631     (clear-stream _test-output-stream)
 6632     (clear-stream $_test-output-buffered-file->buffer)
 6633     (clear-stream _test-error-stream)
 6634     (clear-stream $_test-error-buffered-file->buffer)
 6635     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6636     68/push 0/imm32
 6637     68/push 0/imm32
 6638     89/<- %edx 4/r32/esp
 6639     (tailor-exit-descriptor %edx 0x10)
 6640     #
 6641     (write _test-input-stream "fn foo {\n")
 6642     (write _test-input-stream "  var a: (addr t)\n")
 6643     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6644     (write _test-input-stream "}\n")
 6645     (write _test-input-stream "type t {\n")
 6646     (write _test-input-stream "  x: int\n")
 6647     (write _test-input-stream "}\n")
 6648     # convert
 6649     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6650     # registers except esp clobbered at this point
 6651     # restore ed
 6652     89/<- %edx 4/r32/esp
 6653     (flush _test-output-buffered-file)
 6654     (flush _test-error-buffered-file)
 6655 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6661     # check output
 6662     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 6663     (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")
 6664     # check that stop(1) was called
 6665     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 6666     # don't restore from ebp
 6667     81 0/subop/add %esp 8/imm32
 6668     # . epilogue
 6669     5d/pop-to-ebp
 6670     c3/return
 6671 
 6672 test-get-with-wrong-offset-type:
 6673     # . prologue
 6674     55/push-ebp
 6675     89/<- %ebp 4/r32/esp
 6676     # setup
 6677     (clear-stream _test-input-stream)
 6678     (clear-stream $_test-input-buffered-file->buffer)
 6679     (clear-stream _test-output-stream)
 6680     (clear-stream $_test-output-buffered-file->buffer)
 6681     (clear-stream _test-error-stream)
 6682     (clear-stream $_test-error-buffered-file->buffer)
 6683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6684     68/push 0/imm32
 6685     68/push 0/imm32
 6686     89/<- %edx 4/r32/esp
 6687     (tailor-exit-descriptor %edx 0x10)
 6688     #
 6689     (write _test-input-stream "fn foo {\n")
 6690     (write _test-input-stream "  var a: t\n")
 6691     (write _test-input-stream "  var b: int\n")
 6692     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 6693     (write _test-input-stream "}\n")
 6694     (write _test-input-stream "type t {\n")
 6695     (write _test-input-stream "  x: int\n")
 6696     (write _test-input-stream "}\n")
 6697     # convert
 6698     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6699     # registers except esp clobbered at this point
 6700     # restore ed
 6701     89/<- %edx 4/r32/esp
 6702     (flush _test-output-buffered-file)
 6703     (flush _test-error-buffered-file)
 6704 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6710     # check output
 6711     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 6712     (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")
 6713     # check that stop(1) was called
 6714     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 6715     # don't restore from ebp
 6716     81 0/subop/add %esp 8/imm32
 6717     # . epilogue
 6718     5d/pop-to-ebp
 6719     c3/return
 6720 
 6721 test-get-with-wrong-output-type:
 6722     # . prologue
 6723     55/push-ebp
 6724     89/<- %ebp 4/r32/esp
 6725     # setup
 6726     (clear-stream _test-input-stream)
 6727     (clear-stream $_test-input-buffered-file->buffer)
 6728     (clear-stream _test-output-stream)
 6729     (clear-stream $_test-output-buffered-file->buffer)
 6730     (clear-stream _test-error-stream)
 6731     (clear-stream $_test-error-buffered-file->buffer)
 6732     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6733     68/push 0/imm32
 6734     68/push 0/imm32
 6735     89/<- %edx 4/r32/esp
 6736     (tailor-exit-descriptor %edx 0x10)
 6737     #
 6738     (write _test-input-stream "fn foo {\n")
 6739     (write _test-input-stream "  var a: t\n")
 6740     (write _test-input-stream "  var c: (addr int)\n")
 6741     (write _test-input-stream "  c <- get a, x\n")
 6742     (write _test-input-stream "}\n")
 6743     (write _test-input-stream "type t {\n")
 6744     (write _test-input-stream "  x: int\n")
 6745     (write _test-input-stream "}\n")
 6746     # convert
 6747     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6748     # registers except esp clobbered at this point
 6749     # restore ed
 6750     89/<- %edx 4/r32/esp
 6751     (flush _test-output-buffered-file)
 6752     (flush _test-error-buffered-file)
 6753 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6759     # check output
 6760     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 6761     (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")
 6762     # check that stop(1) was called
 6763     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 6764     # don't restore from ebp
 6765     81 0/subop/add %esp 8/imm32
 6766     # . epilogue
 6767     5d/pop-to-ebp
 6768     c3/return
 6769 
 6770 test-get-with-wrong-output-type-2:
 6771     # . prologue
 6772     55/push-ebp
 6773     89/<- %ebp 4/r32/esp
 6774     # setup
 6775     (clear-stream _test-input-stream)
 6776     (clear-stream $_test-input-buffered-file->buffer)
 6777     (clear-stream _test-output-stream)
 6778     (clear-stream $_test-output-buffered-file->buffer)
 6779     (clear-stream _test-error-stream)
 6780     (clear-stream $_test-error-buffered-file->buffer)
 6781     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6782     68/push 0/imm32
 6783     68/push 0/imm32
 6784     89/<- %edx 4/r32/esp
 6785     (tailor-exit-descriptor %edx 0x10)
 6786     #
 6787     (write _test-input-stream "fn foo {\n")
 6788     (write _test-input-stream "  var a: t\n")
 6789     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 6790     (write _test-input-stream "}\n")
 6791     (write _test-input-stream "type t {\n")
 6792     (write _test-input-stream "  x: int\n")
 6793     (write _test-input-stream "}\n")
 6794     # convert
 6795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6796     # registers except esp clobbered at this point
 6797     # restore ed
 6798     89/<- %edx 4/r32/esp
 6799     (flush _test-output-buffered-file)
 6800     (flush _test-error-buffered-file)
 6801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6807     # check output
 6808     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 6809     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-2: error message")
 6810     # check that stop(1) was called
 6811     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 6812     # don't restore from ebp
 6813     81 0/subop/add %esp 8/imm32
 6814     # . epilogue
 6815     5d/pop-to-ebp
 6816     c3/return
 6817 
 6818 test-get-with-wrong-output-type-3:
 6819     # . prologue
 6820     55/push-ebp
 6821     89/<- %ebp 4/r32/esp
 6822     # setup
 6823     (clear-stream _test-input-stream)
 6824     (clear-stream $_test-input-buffered-file->buffer)
 6825     (clear-stream _test-output-stream)
 6826     (clear-stream $_test-output-buffered-file->buffer)
 6827     (clear-stream _test-error-stream)
 6828     (clear-stream $_test-error-buffered-file->buffer)
 6829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6830     68/push 0/imm32
 6831     68/push 0/imm32
 6832     89/<- %edx 4/r32/esp
 6833     (tailor-exit-descriptor %edx 0x10)
 6834     #
 6835     (write _test-input-stream "fn foo {\n")
 6836     (write _test-input-stream "  var a: t\n")
 6837     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 6838     (write _test-input-stream "}\n")
 6839     (write _test-input-stream "type t {\n")
 6840     (write _test-input-stream "  x: int\n")
 6841     (write _test-input-stream "}\n")
 6842     # convert
 6843     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6844     # registers except esp clobbered at this point
 6845     # restore ed
 6846     89/<- %edx 4/r32/esp
 6847     (flush _test-output-buffered-file)
 6848     (flush _test-error-buffered-file)
 6849 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6855     # check output
 6856     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 6857     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-3: error message")
 6858     # check that stop(1) was called
 6859     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 6860     # don't restore from ebp
 6861     81 0/subop/add %esp 8/imm32
 6862     # . epilogue
 6863     5d/pop-to-ebp
 6864     c3/return
 6865 
 6866 test-get-with-wrong-output-type-4:
 6867     # . prologue
 6868     55/push-ebp
 6869     89/<- %ebp 4/r32/esp
 6870     # setup
 6871     (clear-stream _test-input-stream)
 6872     (clear-stream $_test-input-buffered-file->buffer)
 6873     (clear-stream _test-output-stream)
 6874     (clear-stream $_test-output-buffered-file->buffer)
 6875     (clear-stream _test-error-stream)
 6876     (clear-stream $_test-error-buffered-file->buffer)
 6877     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6878     68/push 0/imm32
 6879     68/push 0/imm32
 6880     89/<- %edx 4/r32/esp
 6881     (tailor-exit-descriptor %edx 0x10)
 6882     #
 6883     (write _test-input-stream "fn foo {\n")
 6884     (write _test-input-stream "  var a: t\n")
 6885     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 6886     (write _test-input-stream "}\n")
 6887     (write _test-input-stream "type t {\n")
 6888     (write _test-input-stream "  x: int\n")
 6889     (write _test-input-stream "}\n")
 6890     # convert
 6891     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6892     # registers except esp clobbered at this point
 6893     # restore ed
 6894     89/<- %edx 4/r32/esp
 6895     (flush _test-output-buffered-file)
 6896     (flush _test-error-buffered-file)
 6897 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6903     # check output
 6904     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 6905     (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")
 6906     # check that stop(1) was called
 6907     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 6908     # don't restore from ebp
 6909     81 0/subop/add %esp 8/imm32
 6910     # . epilogue
 6911     5d/pop-to-ebp
 6912     c3/return
 6913 
 6914 test-get-with-wrong-output-type-5:
 6915     # . prologue
 6916     55/push-ebp
 6917     89/<- %ebp 4/r32/esp
 6918     # setup
 6919     (clear-stream _test-input-stream)
 6920     (clear-stream $_test-input-buffered-file->buffer)
 6921     (clear-stream _test-output-stream)
 6922     (clear-stream $_test-output-buffered-file->buffer)
 6923     #
 6924     (write _test-input-stream "fn foo {\n")
 6925     (write _test-input-stream "  var a: t\n")
 6926     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 6927     (write _test-input-stream "}\n")
 6928     (write _test-input-stream "type t {\n")
 6929     (write _test-input-stream "  x: (handle int)\n")
 6930     (write _test-input-stream "}\n")
 6931     # convert
 6932     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6933     (flush _test-output-buffered-file)
 6934     # no errors
 6935     # . epilogue
 6936     89/<- %esp 5/r32/ebp
 6937     5d/pop-to-ebp
 6938     c3/return
 6939 
 6940 test-get-with-too-few-inouts:
 6941     # . prologue
 6942     55/push-ebp
 6943     89/<- %ebp 4/r32/esp
 6944     # setup
 6945     (clear-stream _test-input-stream)
 6946     (clear-stream $_test-input-buffered-file->buffer)
 6947     (clear-stream _test-output-stream)
 6948     (clear-stream $_test-output-buffered-file->buffer)
 6949     (clear-stream _test-error-stream)
 6950     (clear-stream $_test-error-buffered-file->buffer)
 6951     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6952     68/push 0/imm32
 6953     68/push 0/imm32
 6954     89/<- %edx 4/r32/esp
 6955     (tailor-exit-descriptor %edx 0x10)
 6956     #
 6957     (write _test-input-stream "fn foo {\n")
 6958     (write _test-input-stream "  var a: t\n")
 6959     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 6960     (write _test-input-stream "}\n")
 6961     (write _test-input-stream "type t {\n")
 6962     (write _test-input-stream "  x: int\n")
 6963     (write _test-input-stream "}\n")
 6964     # convert
 6965     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6966     # registers except esp clobbered at this point
 6967     # restore ed
 6968     89/<- %edx 4/r32/esp
 6969     (flush _test-output-buffered-file)
 6970     (flush _test-error-buffered-file)
 6971 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6977     # check output
 6978     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 6979     (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")
 6980     # check that stop(1) was called
 6981     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 6982     # don't restore from ebp
 6983     81 0/subop/add %esp 8/imm32
 6984     # . epilogue
 6985     5d/pop-to-ebp
 6986     c3/return
 6987 
 6988 test-get-with-too-many-inouts:
 6989     # . prologue
 6990     55/push-ebp
 6991     89/<- %ebp 4/r32/esp
 6992     # setup
 6993     (clear-stream _test-input-stream)
 6994     (clear-stream $_test-input-buffered-file->buffer)
 6995     (clear-stream _test-output-stream)
 6996     (clear-stream $_test-output-buffered-file->buffer)
 6997     (clear-stream _test-error-stream)
 6998     (clear-stream $_test-error-buffered-file->buffer)
 6999     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7000     68/push 0/imm32
 7001     68/push 0/imm32
 7002     89/<- %edx 4/r32/esp
 7003     (tailor-exit-descriptor %edx 0x10)
 7004     #
 7005     (write _test-input-stream "fn foo {\n")
 7006     (write _test-input-stream "  var a: t\n")
 7007     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 7008     (write _test-input-stream "}\n")
 7009     (write _test-input-stream "type t {\n")
 7010     (write _test-input-stream "  x: int\n")
 7011     (write _test-input-stream "}\n")
 7012     # convert
 7013     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7014     # registers except esp clobbered at this point
 7015     # restore ed
 7016     89/<- %edx 4/r32/esp
 7017     (flush _test-output-buffered-file)
 7018     (flush _test-error-buffered-file)
 7019 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7025     # check output
 7026     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 7027     (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")
 7028     # check that stop(1) was called
 7029     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 7030     # don't restore from ebp
 7031     81 0/subop/add %esp 8/imm32
 7032     # . epilogue
 7033     5d/pop-to-ebp
 7034     c3/return
 7035 
 7036 test-get-with-no-output:
 7037     # . prologue
 7038     55/push-ebp
 7039     89/<- %ebp 4/r32/esp
 7040     # setup
 7041     (clear-stream _test-input-stream)
 7042     (clear-stream $_test-input-buffered-file->buffer)
 7043     (clear-stream _test-output-stream)
 7044     (clear-stream $_test-output-buffered-file->buffer)
 7045     (clear-stream _test-error-stream)
 7046     (clear-stream $_test-error-buffered-file->buffer)
 7047     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7048     68/push 0/imm32
 7049     68/push 0/imm32
 7050     89/<- %edx 4/r32/esp
 7051     (tailor-exit-descriptor %edx 0x10)
 7052     #
 7053     (write _test-input-stream "fn foo {\n")
 7054     (write _test-input-stream "  var a: t\n")
 7055     (write _test-input-stream "  get a, x\n")
 7056     (write _test-input-stream "}\n")
 7057     (write _test-input-stream "type t {\n")
 7058     (write _test-input-stream "  x: int\n")
 7059     (write _test-input-stream "}\n")
 7060     # convert
 7061     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7062     # registers except esp clobbered at this point
 7063     # restore ed
 7064     89/<- %edx 4/r32/esp
 7065     (flush _test-output-buffered-file)
 7066     (flush _test-error-buffered-file)
 7067 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7073     # check output
 7074     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 7075     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 7076     # check that stop(1) was called
 7077     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 7078     # don't restore from ebp
 7079     81 0/subop/add %esp 8/imm32
 7080     # . epilogue
 7081     5d/pop-to-ebp
 7082     c3/return
 7083 
 7084 test-get-with-too-many-outputs:
 7085     # . prologue
 7086     55/push-ebp
 7087     89/<- %ebp 4/r32/esp
 7088     # setup
 7089     (clear-stream _test-input-stream)
 7090     (clear-stream $_test-input-buffered-file->buffer)
 7091     (clear-stream _test-output-stream)
 7092     (clear-stream $_test-output-buffered-file->buffer)
 7093     (clear-stream _test-error-stream)
 7094     (clear-stream $_test-error-buffered-file->buffer)
 7095     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7096     68/push 0/imm32
 7097     68/push 0/imm32
 7098     89/<- %edx 4/r32/esp
 7099     (tailor-exit-descriptor %edx 0x10)
 7100     #
 7101     (write _test-input-stream "fn foo {\n")
 7102     (write _test-input-stream "  var a: t\n")
 7103     (write _test-input-stream "  var b: int\n")
 7104     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 7105     (write _test-input-stream "  c, b <- get a, x\n")
 7106     (write _test-input-stream "}\n")
 7107     (write _test-input-stream "type t {\n")
 7108     (write _test-input-stream "  x: int\n")
 7109     (write _test-input-stream "}\n")
 7110     # convert
 7111     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7112     # registers except esp clobbered at this point
 7113     # restore ed
 7114     89/<- %edx 4/r32/esp
 7115     (flush _test-output-buffered-file)
 7116     (flush _test-error-buffered-file)
 7117 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7123     # check output
 7124     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 7125     (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")
 7126     # check that stop(1) was called
 7127     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 7128     # don't restore from ebp
 7129     81 0/subop/add %esp 8/imm32
 7130     # . epilogue
 7131     5d/pop-to-ebp
 7132     c3/return
 7133 
 7134 test-convert-array-of-user-defined-types:
 7135     # . prologue
 7136     55/push-ebp
 7137     89/<- %ebp 4/r32/esp
 7138     # setup
 7139     (clear-stream _test-input-stream)
 7140     (clear-stream $_test-input-buffered-file->buffer)
 7141     (clear-stream _test-output-stream)
 7142     (clear-stream $_test-output-buffered-file->buffer)
 7143     #
 7144     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 7145     (write _test-input-stream "  x: int\n")
 7146     (write _test-input-stream "  y: int\n")
 7147     (write _test-input-stream "}\n")
 7148     (write _test-input-stream "fn foo {\n")
 7149     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 7150     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 7151     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 7152     (write _test-input-stream "}\n")
 7153     # convert
 7154     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7155     (flush _test-output-buffered-file)
 7156 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7162     # check output
 7163     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 7164     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 7165     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 7166     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 7167     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 7168     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 7169     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 7170     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 7171     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 7172     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 7173     (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")
 7174     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/13")
 7175     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/14")
 7176     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/15")
 7177     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/16")
 7178     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/17")
 7179     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/18")
 7180     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/19")
 7181     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/20")
 7182     # . epilogue
 7183     89/<- %esp 5/r32/ebp
 7184     5d/pop-to-ebp
 7185     c3/return
 7186 
 7187 test-convert-length-of-array-of-user-defined-types-to-eax:
 7188     # . prologue
 7189     55/push-ebp
 7190     89/<- %ebp 4/r32/esp
 7191     # setup
 7192     (clear-stream _test-input-stream)
 7193     (clear-stream $_test-input-buffered-file->buffer)
 7194     (clear-stream _test-output-stream)
 7195     (clear-stream $_test-output-buffered-file->buffer)
 7196     #
 7197     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 7198     (write _test-input-stream "  x: int\n")
 7199     (write _test-input-stream "  y: int\n")
 7200     (write _test-input-stream "  z: int\n")
 7201     (write _test-input-stream "}\n")
 7202     (write _test-input-stream "fn foo {\n")
 7203     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 7204     (write _test-input-stream "  var x/eax: int <- length arr\n")
 7205     (write _test-input-stream "}\n")
 7206     # convert
 7207     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7208     (flush _test-output-buffered-file)
 7209 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7215     # check output
 7216     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 7217     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 7218     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 7219     (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")
 7220     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 7221     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 7222     # var arr
 7223     (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")
 7224     (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")
 7225     # length instruction
 7226     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 7227     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 7228     (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")
 7229     (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")
 7230     (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")
 7231     (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")
 7232     (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")
 7233     (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")
 7234     # reclaim arr
 7235     (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")
 7236     #
 7237     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 7238     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 7239     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 7240     (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")
 7241     (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")
 7242     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 7243     # . epilogue
 7244     89/<- %esp 5/r32/ebp
 7245     5d/pop-to-ebp
 7246     c3/return
 7247 
 7248 test-convert-length-of-array-of-user-defined-types-to-ecx:
 7249     # . prologue
 7250     55/push-ebp
 7251     89/<- %ebp 4/r32/esp
 7252     # setup
 7253     (clear-stream _test-input-stream)
 7254     (clear-stream $_test-input-buffered-file->buffer)
 7255     (clear-stream _test-output-stream)
 7256     (clear-stream $_test-output-buffered-file->buffer)
 7257     #
 7258     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 7259     (write _test-input-stream "  x: int\n")
 7260     (write _test-input-stream "  y: int\n")
 7261     (write _test-input-stream "  z: int\n")
 7262     (write _test-input-stream "}\n")
 7263     (write _test-input-stream "fn foo {\n")
 7264     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 7265     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 7266     (write _test-input-stream "}\n")
 7267     # convert
 7268     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7269     (flush _test-output-buffered-file)
 7270 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7276     # check output
 7277     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 7278     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 7279     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 7280     (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")
 7281     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 7282     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 7283     # var a
 7284     (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")
 7285     (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")
 7286     # var x
 7287     (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")
 7288     # length instruction
 7289     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 7290     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 7291     (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")
 7292     (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")
 7293     (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")
 7294     (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")
 7295     (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")
 7296     (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")
 7297     (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")
 7298     # reclaim x
 7299     (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")
 7300     # reclaim a
 7301     (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")
 7302     #
 7303     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 7304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 7305     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 7306     (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")
 7307     (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")
 7308     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 7309     # . epilogue
 7310     89/<- %esp 5/r32/ebp
 7311     5d/pop-to-ebp
 7312     c3/return
 7313 
 7314 test-convert-length-of-array-of-user-defined-types-to-edx:
 7315     # . prologue
 7316     55/push-ebp
 7317     89/<- %ebp 4/r32/esp
 7318     # setup
 7319     (clear-stream _test-input-stream)
 7320     (clear-stream $_test-input-buffered-file->buffer)
 7321     (clear-stream _test-output-stream)
 7322     (clear-stream $_test-output-buffered-file->buffer)
 7323     #
 7324     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 7325     (write _test-input-stream "  x: int\n")
 7326     (write _test-input-stream "  y: int\n")
 7327     (write _test-input-stream "  z: int\n")
 7328     (write _test-input-stream "}\n")
 7329     (write _test-input-stream "fn foo {\n")
 7330     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 7331     (write _test-input-stream "  var x/edx: int <- length arr\n")
 7332     (write _test-input-stream "}\n")
 7333     # convert
 7334     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7335     (flush _test-output-buffered-file)
 7336 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7342     # check output
 7343     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 7344     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 7345     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 7346     (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")
 7347     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 7348     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 7349     # var a
 7350     (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")
 7351     (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")
 7352     # var x
 7353     (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")
 7354     # length instruction
 7355     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 7356     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 7357     (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")
 7358     (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")
 7359     (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")
 7360     (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")
 7361     (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")
 7362     (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")
 7363     (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")
 7364     # reclaim x
 7365     (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")
 7366     # reclaim a
 7367     (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")
 7368     #
 7369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 7370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 7371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 7372     (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")
 7373     (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")
 7374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 7375     # . epilogue
 7376     89/<- %esp 5/r32/ebp
 7377     5d/pop-to-ebp
 7378     c3/return
 7379 
 7380 test-convert-length-of-array-of-user-defined-types:
 7381     # . prologue
 7382     55/push-ebp
 7383     89/<- %ebp 4/r32/esp
 7384     # setup
 7385     (clear-stream _test-input-stream)
 7386     (clear-stream $_test-input-buffered-file->buffer)
 7387     (clear-stream _test-output-stream)
 7388     (clear-stream $_test-output-buffered-file->buffer)
 7389     #
 7390     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 7391     (write _test-input-stream "  x: int\n")
 7392     (write _test-input-stream "  y: int\n")
 7393     (write _test-input-stream "  z: int\n")
 7394     (write _test-input-stream "}\n")
 7395     (write _test-input-stream "fn foo {\n")
 7396     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 7397     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 7398     (write _test-input-stream "}\n")
 7399     # convert
 7400     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7401     (flush _test-output-buffered-file)
 7402 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7408     # check output
 7409     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 7410     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 7411     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 7412     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 7413     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 7414     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 7415     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 7416     (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")
 7417     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 7418     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 7419     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 7420     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 7421     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 7422     (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")
 7423     (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")
 7424     (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")
 7425     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 7426     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 7427     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 7428     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 7429     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 7430     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 7431     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 7432     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 7433     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 7434     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 7435     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 7436     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 7437     # . epilogue
 7438     89/<- %esp 5/r32/ebp
 7439     5d/pop-to-ebp
 7440     c3/return
 7441 
 7442 test-index-with-non-array-atom-base-type:
 7443     # . prologue
 7444     55/push-ebp
 7445     89/<- %ebp 4/r32/esp
 7446     # setup
 7447     (clear-stream _test-input-stream)
 7448     (clear-stream $_test-input-buffered-file->buffer)
 7449     (clear-stream _test-output-stream)
 7450     (clear-stream $_test-output-buffered-file->buffer)
 7451     (clear-stream _test-error-stream)
 7452     (clear-stream $_test-error-buffered-file->buffer)
 7453     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7454     68/push 0/imm32
 7455     68/push 0/imm32
 7456     89/<- %edx 4/r32/esp
 7457     (tailor-exit-descriptor %edx 0x10)
 7458     #
 7459     (write _test-input-stream "fn foo {\n")
 7460     (write _test-input-stream "  var a: int\n")
 7461     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7462     (write _test-input-stream "}\n")
 7463     # convert
 7464     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7465     # registers except esp clobbered at this point
 7466     # restore ed
 7467     89/<- %edx 4/r32/esp
 7468     (flush _test-output-buffered-file)
 7469     (flush _test-error-buffered-file)
 7470 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7476     # check output
 7477     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 7478     (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")
 7479     # check that stop(1) was called
 7480     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 7481     # don't restore from ebp
 7482     81 0/subop/add %esp 8/imm32
 7483     # . epilogue
 7484     5d/pop-to-ebp
 7485     c3/return
 7486 
 7487 test-index-with-non-array-compound-base-type:
 7488     # . prologue
 7489     55/push-ebp
 7490     89/<- %ebp 4/r32/esp
 7491     # setup
 7492     (clear-stream _test-input-stream)
 7493     (clear-stream $_test-input-buffered-file->buffer)
 7494     (clear-stream _test-output-stream)
 7495     (clear-stream $_test-output-buffered-file->buffer)
 7496     (clear-stream _test-error-stream)
 7497     (clear-stream $_test-error-buffered-file->buffer)
 7498     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7499     68/push 0/imm32
 7500     68/push 0/imm32
 7501     89/<- %edx 4/r32/esp
 7502     (tailor-exit-descriptor %edx 0x10)
 7503     #
 7504     (write _test-input-stream "fn foo {\n")
 7505     (write _test-input-stream "  var a: (handle int)\n")
 7506     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7507     (write _test-input-stream "}\n")
 7508     # convert
 7509     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7510     # registers except esp clobbered at this point
 7511     # restore ed
 7512     89/<- %edx 4/r32/esp
 7513     (flush _test-output-buffered-file)
 7514     (flush _test-error-buffered-file)
 7515 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7521     # check output
 7522     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 7523     (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")
 7524     # check that stop(1) was called
 7525     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 7526     # don't restore from ebp
 7527     81 0/subop/add %esp 8/imm32
 7528     # . epilogue
 7529     5d/pop-to-ebp
 7530     c3/return
 7531 
 7532 test-index-with-non-array-compound-base-type-2:
 7533     # . prologue
 7534     55/push-ebp
 7535     89/<- %ebp 4/r32/esp
 7536     # setup
 7537     (clear-stream _test-input-stream)
 7538     (clear-stream $_test-input-buffered-file->buffer)
 7539     (clear-stream _test-output-stream)
 7540     (clear-stream $_test-output-buffered-file->buffer)
 7541     (clear-stream _test-error-stream)
 7542     (clear-stream $_test-error-buffered-file->buffer)
 7543     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7544     68/push 0/imm32
 7545     68/push 0/imm32
 7546     89/<- %edx 4/r32/esp
 7547     (tailor-exit-descriptor %edx 0x10)
 7548     #
 7549     (write _test-input-stream "fn foo {\n")
 7550     (write _test-input-stream "  var a: (addr int)\n")
 7551     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7552     (write _test-input-stream "}\n")
 7553     # convert
 7554     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7555     # registers except esp clobbered at this point
 7556     # restore ed
 7557     89/<- %edx 4/r32/esp
 7558     (flush _test-output-buffered-file)
 7559     (flush _test-error-buffered-file)
 7560 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7566     # check output
 7567     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 7568     (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")
 7569     # check that stop(1) was called
 7570     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 7571     # don't restore from ebp
 7572     81 0/subop/add %esp 8/imm32
 7573     # . epilogue
 7574     5d/pop-to-ebp
 7575     c3/return
 7576 
 7577 test-index-with-array-atom-base-type:
 7578     # . prologue
 7579     55/push-ebp
 7580     89/<- %ebp 4/r32/esp
 7581     # setup
 7582     (clear-stream _test-input-stream)
 7583     (clear-stream $_test-input-buffered-file->buffer)
 7584     (clear-stream _test-output-stream)
 7585     (clear-stream $_test-output-buffered-file->buffer)
 7586     (clear-stream _test-error-stream)
 7587     (clear-stream $_test-error-buffered-file->buffer)
 7588     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7589     68/push 0/imm32
 7590     68/push 0/imm32
 7591     89/<- %edx 4/r32/esp
 7592     (tailor-exit-descriptor %edx 0x10)
 7593     #
 7594     (write _test-input-stream "fn foo {\n")
 7595     (write _test-input-stream "  var a: array\n")
 7596     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7597     (write _test-input-stream "}\n")
 7598     # convert
 7599     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7600     # registers except esp clobbered at this point
 7601     # restore ed
 7602     89/<- %edx 4/r32/esp
 7603     (flush _test-output-buffered-file)
 7604     (flush _test-error-buffered-file)
 7605 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7611     # check output
 7612     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 7613     (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")
 7614     # check that stop(1) was called
 7615     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 7616     # don't restore from ebp
 7617     81 0/subop/add %esp 8/imm32
 7618     # . epilogue
 7619     5d/pop-to-ebp
 7620     c3/return
 7621 
 7622 test-index-with-addr-base-on-stack:
 7623     # . prologue
 7624     55/push-ebp
 7625     89/<- %ebp 4/r32/esp
 7626     # setup
 7627     (clear-stream _test-input-stream)
 7628     (clear-stream $_test-input-buffered-file->buffer)
 7629     (clear-stream _test-output-stream)
 7630     (clear-stream $_test-output-buffered-file->buffer)
 7631     (clear-stream _test-error-stream)
 7632     (clear-stream $_test-error-buffered-file->buffer)
 7633     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7634     68/push 0/imm32
 7635     68/push 0/imm32
 7636     89/<- %edx 4/r32/esp
 7637     (tailor-exit-descriptor %edx 0x10)
 7638     #
 7639     (write _test-input-stream "fn foo {\n")
 7640     (write _test-input-stream "  var a: (addr array int)\n")
 7641     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7642     (write _test-input-stream "}\n")
 7643     # convert
 7644     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7645     # registers except esp clobbered at this point
 7646     # restore ed
 7647     89/<- %edx 4/r32/esp
 7648     (flush _test-output-buffered-file)
 7649     (flush _test-error-buffered-file)
 7650 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7656     # check output
 7657     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
 7658     (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")
 7659     # check that stop(1) was called
 7660     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
 7661     # don't restore from ebp
 7662     81 0/subop/add %esp 8/imm32
 7663     # . epilogue
 7664     5d/pop-to-ebp
 7665     c3/return
 7666 
 7667 test-index-with-array-base-in-register:
 7668     # . prologue
 7669     55/push-ebp
 7670     89/<- %ebp 4/r32/esp
 7671     # setup
 7672     (clear-stream _test-input-stream)
 7673     (clear-stream $_test-input-buffered-file->buffer)
 7674     (clear-stream _test-output-stream)
 7675     (clear-stream $_test-output-buffered-file->buffer)
 7676     (clear-stream _test-error-stream)
 7677     (clear-stream $_test-error-buffered-file->buffer)
 7678     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7679     68/push 0/imm32
 7680     68/push 0/imm32
 7681     89/<- %edx 4/r32/esp
 7682     (tailor-exit-descriptor %edx 0x10)
 7683     #
 7684     (write _test-input-stream "fn foo {\n")
 7685     (write _test-input-stream "  var a/eax: (array int 3) <- copy 0\n")
 7686     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7687     (write _test-input-stream "}\n")
 7688     # convert
 7689     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7690     # registers except esp clobbered at this point
 7691     # restore ed
 7692     89/<- %edx 4/r32/esp
 7693     (flush _test-output-buffered-file)
 7694     (flush _test-error-buffered-file)
 7695 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7701     # check output
 7702     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-base-in-register: output should be empty")
 7703     (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")
 7704     # check that stop(1) was called
 7705     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-base-in-register: exit status")
 7706     # don't restore from ebp
 7707     81 0/subop/add %esp 8/imm32
 7708     # . epilogue
 7709     5d/pop-to-ebp
 7710     c3/return
 7711 
 7712 test-index-with-wrong-index-type:
 7713     # . prologue
 7714     55/push-ebp
 7715     89/<- %ebp 4/r32/esp
 7716     # setup
 7717     (clear-stream _test-input-stream)
 7718     (clear-stream $_test-input-buffered-file->buffer)
 7719     (clear-stream _test-output-stream)
 7720     (clear-stream $_test-output-buffered-file->buffer)
 7721     (clear-stream _test-error-stream)
 7722     (clear-stream $_test-error-buffered-file->buffer)
 7723     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7724     68/push 0/imm32
 7725     68/push 0/imm32
 7726     89/<- %edx 4/r32/esp
 7727     (tailor-exit-descriptor %edx 0x10)
 7728     #
 7729     (write _test-input-stream "fn foo {\n")
 7730     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7731     (write _test-input-stream "  var b: boolean\n")
 7732     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7733     (write _test-input-stream "}\n")
 7734     # convert
 7735     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7736     # registers except esp clobbered at this point
 7737     # restore ed
 7738     89/<- %edx 4/r32/esp
 7739     (flush _test-output-buffered-file)
 7740     (flush _test-error-buffered-file)
 7741 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7747     # check output
 7748     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
 7749     (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")
 7750     # check that stop(1) was called
 7751     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
 7752     # don't restore from ebp
 7753     81 0/subop/add %esp 8/imm32
 7754     # . epilogue
 7755     5d/pop-to-ebp
 7756     c3/return
 7757 
 7758 test-index-with-offset-atom-index-type:
 7759     # . prologue
 7760     55/push-ebp
 7761     89/<- %ebp 4/r32/esp
 7762     # setup
 7763     (clear-stream _test-input-stream)
 7764     (clear-stream $_test-input-buffered-file->buffer)
 7765     (clear-stream _test-output-stream)
 7766     (clear-stream $_test-output-buffered-file->buffer)
 7767     (clear-stream _test-error-stream)
 7768     (clear-stream $_test-error-buffered-file->buffer)
 7769     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7770     68/push 0/imm32
 7771     68/push 0/imm32
 7772     89/<- %edx 4/r32/esp
 7773     (tailor-exit-descriptor %edx 0x10)
 7774     #
 7775     (write _test-input-stream "fn foo {\n")
 7776     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7777     (write _test-input-stream "  var b: offset\n")
 7778     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7779     (write _test-input-stream "}\n")
 7780     # convert
 7781     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7782     # registers except esp clobbered at this point
 7783     # restore ed
 7784     89/<- %edx 4/r32/esp
 7785     (flush _test-output-buffered-file)
 7786     (flush _test-error-buffered-file)
 7787 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7793     # check output
 7794     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
 7795     (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")
 7796     # check that stop(1) was called
 7797     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
 7798     # don't restore from ebp
 7799     81 0/subop/add %esp 8/imm32
 7800     # . epilogue
 7801     5d/pop-to-ebp
 7802     c3/return
 7803 
 7804 test-index-with-offset-on-stack:
 7805     # . prologue
 7806     55/push-ebp
 7807     89/<- %ebp 4/r32/esp
 7808     # setup
 7809     (clear-stream _test-input-stream)
 7810     (clear-stream $_test-input-buffered-file->buffer)
 7811     (clear-stream _test-output-stream)
 7812     (clear-stream $_test-output-buffered-file->buffer)
 7813     (clear-stream _test-error-stream)
 7814     (clear-stream $_test-error-buffered-file->buffer)
 7815     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7816     68/push 0/imm32
 7817     68/push 0/imm32
 7818     89/<- %edx 4/r32/esp
 7819     (tailor-exit-descriptor %edx 0x10)
 7820     #
 7821     (write _test-input-stream "fn foo {\n")
 7822     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7823     (write _test-input-stream "  var b: int\n")
 7824     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7825     (write _test-input-stream "}\n")
 7826     # convert
 7827     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7828     # registers except esp clobbered at this point
 7829     # restore ed
 7830     89/<- %edx 4/r32/esp
 7831     (flush _test-output-buffered-file)
 7832     (flush _test-error-buffered-file)
 7833 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7839     # check output
 7840     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
 7841     (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")
 7842     # check that stop(1) was called
 7843     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
 7844     # don't restore from ebp
 7845     81 0/subop/add %esp 8/imm32
 7846     # . epilogue
 7847     5d/pop-to-ebp
 7848     c3/return
 7849 
 7850 test-index-needs-offset-type:
 7851     # . prologue
 7852     55/push-ebp
 7853     89/<- %ebp 4/r32/esp
 7854     # setup
 7855     (clear-stream _test-input-stream)
 7856     (clear-stream $_test-input-buffered-file->buffer)
 7857     (clear-stream _test-output-stream)
 7858     (clear-stream $_test-output-buffered-file->buffer)
 7859     (clear-stream _test-error-stream)
 7860     (clear-stream $_test-error-buffered-file->buffer)
 7861     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7862     68/push 0/imm32
 7863     68/push 0/imm32
 7864     89/<- %edx 4/r32/esp
 7865     (tailor-exit-descriptor %edx 0x10)
 7866     #
 7867     (write _test-input-stream "fn foo {\n")
 7868     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
 7869     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7870     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7871     (write _test-input-stream "}\n")
 7872     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
 7873     (write _test-input-stream "  x: int\n")
 7874     (write _test-input-stream "  y: int\n")
 7875     (write _test-input-stream "  z: int\n")
 7876     (write _test-input-stream "}\n")
 7877     # convert
 7878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7879     # registers except esp clobbered at this point
 7880     # restore ed
 7881     89/<- %edx 4/r32/esp
 7882     (flush _test-output-buffered-file)
 7883     (flush _test-error-buffered-file)
 7884 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7890     # check output
 7891     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
 7892     (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")
 7893     # check that stop(1) was called
 7894     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
 7895     # don't restore from ebp
 7896     81 0/subop/add %esp 8/imm32
 7897     # . epilogue
 7898     5d/pop-to-ebp
 7899     c3/return
 7900 
 7901 test-index-with-output-not-address:
 7902     # . prologue
 7903     55/push-ebp
 7904     89/<- %ebp 4/r32/esp
 7905     # setup
 7906     (clear-stream _test-input-stream)
 7907     (clear-stream $_test-input-buffered-file->buffer)
 7908     (clear-stream _test-output-stream)
 7909     (clear-stream $_test-output-buffered-file->buffer)
 7910     (clear-stream _test-error-stream)
 7911     (clear-stream $_test-error-buffered-file->buffer)
 7912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7913     68/push 0/imm32
 7914     68/push 0/imm32
 7915     89/<- %edx 4/r32/esp
 7916     (tailor-exit-descriptor %edx 0x10)
 7917     #
 7918     (write _test-input-stream "fn foo {\n")
 7919     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7920     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
 7921     (write _test-input-stream "}\n")
 7922     # convert
 7923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7924     # registers except esp clobbered at this point
 7925     # restore ed
 7926     89/<- %edx 4/r32/esp
 7927     (flush _test-output-buffered-file)
 7928     (flush _test-error-buffered-file)
 7929 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7935     # check output
 7936     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
 7937     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address: error message")
 7938     # check that stop(1) was called
 7939     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
 7940     # don't restore from ebp
 7941     81 0/subop/add %esp 8/imm32
 7942     # . epilogue
 7943     5d/pop-to-ebp
 7944     c3/return
 7945 
 7946 test-index-with-output-not-address-2:
 7947     # . prologue
 7948     55/push-ebp
 7949     89/<- %ebp 4/r32/esp
 7950     # setup
 7951     (clear-stream _test-input-stream)
 7952     (clear-stream $_test-input-buffered-file->buffer)
 7953     (clear-stream _test-output-stream)
 7954     (clear-stream $_test-output-buffered-file->buffer)
 7955     (clear-stream _test-error-stream)
 7956     (clear-stream $_test-error-buffered-file->buffer)
 7957     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7958     68/push 0/imm32
 7959     68/push 0/imm32
 7960     89/<- %edx 4/r32/esp
 7961     (tailor-exit-descriptor %edx 0x10)
 7962     #
 7963     (write _test-input-stream "fn foo {\n")
 7964     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7965     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
 7966     (write _test-input-stream "}\n")
 7967     # convert
 7968     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7969     # registers except esp clobbered at this point
 7970     # restore ed
 7971     89/<- %edx 4/r32/esp
 7972     (flush _test-output-buffered-file)
 7973     (flush _test-error-buffered-file)
 7974 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7980     # check output
 7981     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
 7982     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address-2: error message")
 7983     # check that stop(1) was called
 7984     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
 7985     # don't restore from ebp
 7986     81 0/subop/add %esp 8/imm32
 7987     # . epilogue
 7988     5d/pop-to-ebp
 7989     c3/return
 7990 
 7991 test-index-with-wrong-output-type:
 7992     # . prologue
 7993     55/push-ebp
 7994     89/<- %ebp 4/r32/esp
 7995     # setup
 7996     (clear-stream _test-input-stream)
 7997     (clear-stream $_test-input-buffered-file->buffer)
 7998     (clear-stream _test-output-stream)
 7999     (clear-stream $_test-output-buffered-file->buffer)
 8000     (clear-stream _test-error-stream)
 8001     (clear-stream $_test-error-buffered-file->buffer)
 8002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8003     68/push 0/imm32
 8004     68/push 0/imm32
 8005     89/<- %edx 4/r32/esp
 8006     (tailor-exit-descriptor %edx 0x10)
 8007     #
 8008     (write _test-input-stream "fn foo {\n")
 8009     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8010     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
 8011     (write _test-input-stream "}\n")
 8012     # convert
 8013     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8014     # registers except esp clobbered at this point
 8015     # restore ed
 8016     89/<- %edx 4/r32/esp
 8017     (flush _test-output-buffered-file)
 8018     (flush _test-error-buffered-file)
 8019 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8025     # check output
 8026     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
 8027     (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")
 8028     # check that stop(1) was called
 8029     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
 8030     # don't restore from ebp
 8031     81 0/subop/add %esp 8/imm32
 8032     # . epilogue
 8033     5d/pop-to-ebp
 8034     c3/return
 8035 
 8036 test-index-with-wrong-output-compound-type:
 8037     # . prologue
 8038     55/push-ebp
 8039     89/<- %ebp 4/r32/esp
 8040     # setup
 8041     (clear-stream _test-input-stream)
 8042     (clear-stream $_test-input-buffered-file->buffer)
 8043     (clear-stream _test-output-stream)
 8044     (clear-stream $_test-output-buffered-file->buffer)
 8045     (clear-stream _test-error-stream)
 8046     (clear-stream $_test-error-buffered-file->buffer)
 8047     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8048     68/push 0/imm32
 8049     68/push 0/imm32
 8050     89/<- %edx 4/r32/esp
 8051     (tailor-exit-descriptor %edx 0x10)
 8052     #
 8053     (write _test-input-stream "fn foo {\n")
 8054     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 8055     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
 8056     (write _test-input-stream "}\n")
 8057     # convert
 8058     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8059     # registers except esp clobbered at this point
 8060     # restore ed
 8061     89/<- %edx 4/r32/esp
 8062     (flush _test-output-buffered-file)
 8063     (flush _test-error-buffered-file)
 8064 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8070     # check output
 8071     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
 8072     (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")
 8073     # check that stop(1) was called
 8074     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
 8075     # don't restore from ebp
 8076     81 0/subop/add %esp 8/imm32
 8077     # . epilogue
 8078     5d/pop-to-ebp
 8079     c3/return
 8080 
 8081 test-index-with-no-inouts:
 8082     # . prologue
 8083     55/push-ebp
 8084     89/<- %ebp 4/r32/esp
 8085     # setup
 8086     (clear-stream _test-input-stream)
 8087     (clear-stream $_test-input-buffered-file->buffer)
 8088     (clear-stream _test-output-stream)
 8089     (clear-stream $_test-output-buffered-file->buffer)
 8090     (clear-stream _test-error-stream)
 8091     (clear-stream $_test-error-buffered-file->buffer)
 8092     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8093     68/push 0/imm32
 8094     68/push 0/imm32
 8095     89/<- %edx 4/r32/esp
 8096     (tailor-exit-descriptor %edx 0x10)
 8097     #
 8098     (write _test-input-stream "fn foo {\n")
 8099     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
 8100     (write _test-input-stream "}\n")
 8101     # convert
 8102     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8103     # registers except esp clobbered at this point
 8104     # restore ed
 8105     89/<- %edx 4/r32/esp
 8106     (flush _test-output-buffered-file)
 8107     (flush _test-error-buffered-file)
 8108 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8114     # check output
 8115     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
 8116     (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")
 8117     # check that stop(1) was called
 8118     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
 8119     # don't restore from ebp
 8120     81 0/subop/add %esp 8/imm32
 8121     # . epilogue
 8122     5d/pop-to-ebp
 8123     c3/return
 8124 
 8125 test-index-with-too-few-inouts:
 8126     # . prologue
 8127     55/push-ebp
 8128     89/<- %ebp 4/r32/esp
 8129     # setup
 8130     (clear-stream _test-input-stream)
 8131     (clear-stream $_test-input-buffered-file->buffer)
 8132     (clear-stream _test-output-stream)
 8133     (clear-stream $_test-output-buffered-file->buffer)
 8134     (clear-stream _test-error-stream)
 8135     (clear-stream $_test-error-buffered-file->buffer)
 8136     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8137     68/push 0/imm32
 8138     68/push 0/imm32
 8139     89/<- %edx 4/r32/esp
 8140     (tailor-exit-descriptor %edx 0x10)
 8141     #
 8142     (write _test-input-stream "fn foo {\n")
 8143     (write _test-input-stream "  var a: (array int 3)\n")
 8144     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
 8145     (write _test-input-stream "}\n")
 8146     # convert
 8147     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8148     # registers except esp clobbered at this point
 8149     # restore ed
 8150     89/<- %edx 4/r32/esp
 8151     (flush _test-output-buffered-file)
 8152     (flush _test-error-buffered-file)
 8153 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8159     # check output
 8160     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
 8161     (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")
 8162     # check that stop(1) was called
 8163     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
 8164     # don't restore from ebp
 8165     81 0/subop/add %esp 8/imm32
 8166     # . epilogue
 8167     5d/pop-to-ebp
 8168     c3/return
 8169 
 8170 test-index-with-too-many-inouts:
 8171     # . prologue
 8172     55/push-ebp
 8173     89/<- %ebp 4/r32/esp
 8174     # setup
 8175     (clear-stream _test-input-stream)
 8176     (clear-stream $_test-input-buffered-file->buffer)
 8177     (clear-stream _test-output-stream)
 8178     (clear-stream $_test-output-buffered-file->buffer)
 8179     (clear-stream _test-error-stream)
 8180     (clear-stream $_test-error-buffered-file->buffer)
 8181     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8182     68/push 0/imm32
 8183     68/push 0/imm32
 8184     89/<- %edx 4/r32/esp
 8185     (tailor-exit-descriptor %edx 0x10)
 8186     #
 8187     (write _test-input-stream "fn foo {\n")
 8188     (write _test-input-stream "  var a: (array int 3)\n")
 8189     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
 8190     (write _test-input-stream "}\n")
 8191     # convert
 8192     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8193     # registers except esp clobbered at this point
 8194     # restore ed
 8195     89/<- %edx 4/r32/esp
 8196     (flush _test-output-buffered-file)
 8197     (flush _test-error-buffered-file)
 8198 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8204     # check output
 8205     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
 8206     (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")
 8207     # check that stop(1) was called
 8208     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
 8209     # don't restore from ebp
 8210     81 0/subop/add %esp 8/imm32
 8211     # . epilogue
 8212     5d/pop-to-ebp
 8213     c3/return
 8214 
 8215 test-index-with-no-output:
 8216     # . prologue
 8217     55/push-ebp
 8218     89/<- %ebp 4/r32/esp
 8219     # setup
 8220     (clear-stream _test-input-stream)
 8221     (clear-stream $_test-input-buffered-file->buffer)
 8222     (clear-stream _test-output-stream)
 8223     (clear-stream $_test-output-buffered-file->buffer)
 8224     (clear-stream _test-error-stream)
 8225     (clear-stream $_test-error-buffered-file->buffer)
 8226     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8227     68/push 0/imm32
 8228     68/push 0/imm32
 8229     89/<- %edx 4/r32/esp
 8230     (tailor-exit-descriptor %edx 0x10)
 8231     #
 8232     (write _test-input-stream "fn foo {\n")
 8233     (write _test-input-stream "  var a: (array int 3)\n")
 8234     (write _test-input-stream "  index a, 0\n")
 8235     (write _test-input-stream "}\n")
 8236     # convert
 8237     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8238     # registers except esp clobbered at this point
 8239     # restore ed
 8240     89/<- %edx 4/r32/esp
 8241     (flush _test-output-buffered-file)
 8242     (flush _test-error-buffered-file)
 8243 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8249     # check output
 8250     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
 8251     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
 8252     # check that stop(1) was called
 8253     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
 8254     # don't restore from ebp
 8255     81 0/subop/add %esp 8/imm32
 8256     # . epilogue
 8257     5d/pop-to-ebp
 8258     c3/return
 8259 
 8260 test-index-with-too-many-outputs:
 8261     # . prologue
 8262     55/push-ebp
 8263     89/<- %ebp 4/r32/esp
 8264     # setup
 8265     (clear-stream _test-input-stream)
 8266     (clear-stream $_test-input-buffered-file->buffer)
 8267     (clear-stream _test-output-stream)
 8268     (clear-stream $_test-output-buffered-file->buffer)
 8269     (clear-stream _test-error-stream)
 8270     (clear-stream $_test-error-buffered-file->buffer)
 8271     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8272     68/push 0/imm32
 8273     68/push 0/imm32
 8274     89/<- %edx 4/r32/esp
 8275     (tailor-exit-descriptor %edx 0x10)
 8276     #
 8277     (write _test-input-stream "fn foo {\n")
 8278     (write _test-input-stream "  var a: (array int 3)\n")
 8279     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 8280     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
 8281     (write _test-input-stream "  b, c <- index a, 0\n")
 8282     (write _test-input-stream "}\n")
 8283     # convert
 8284     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8285     # registers except esp clobbered at this point
 8286     # restore ed
 8287     89/<- %edx 4/r32/esp
 8288     (flush _test-output-buffered-file)
 8289     (flush _test-error-buffered-file)
 8290 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8296     # check output
 8297     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
 8298     (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")
 8299     # check that stop(1) was called
 8300     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
 8301     # don't restore from ebp
 8302     81 0/subop/add %esp 8/imm32
 8303     # . epilogue
 8304     5d/pop-to-ebp
 8305     c3/return
 8306 
 8307 test-compute-offset-with-non-array-atom-base-type:
 8308     # . prologue
 8309     55/push-ebp
 8310     89/<- %ebp 4/r32/esp
 8311     # setup
 8312     (clear-stream _test-input-stream)
 8313     (clear-stream $_test-input-buffered-file->buffer)
 8314     (clear-stream _test-output-stream)
 8315     (clear-stream $_test-output-buffered-file->buffer)
 8316     (clear-stream _test-error-stream)
 8317     (clear-stream $_test-error-buffered-file->buffer)
 8318     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8319     68/push 0/imm32
 8320     68/push 0/imm32
 8321     89/<- %edx 4/r32/esp
 8322     (tailor-exit-descriptor %edx 0x10)
 8323     #
 8324     (write _test-input-stream "fn foo {\n")
 8325     (write _test-input-stream "  var a: int\n")
 8326     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 8327     (write _test-input-stream "}\n")
 8328     # convert
 8329     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8330     # registers except esp clobbered at this point
 8331     # restore ed
 8332     89/<- %edx 4/r32/esp
 8333     (flush _test-output-buffered-file)
 8334     (flush _test-error-buffered-file)
 8335 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8341     # check output
 8342     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
 8343     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-atom-base-type: error message")
 8344     # check that stop(1) was called
 8345     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
 8346     # don't restore from ebp
 8347     81 0/subop/add %esp 8/imm32
 8348     # . epilogue
 8349     5d/pop-to-ebp
 8350     c3/return
 8351 
 8352 test-compute-offset-with-non-array-compound-base-type:
 8353     # . prologue
 8354     55/push-ebp
 8355     89/<- %ebp 4/r32/esp
 8356     # setup
 8357     (clear-stream _test-input-stream)
 8358     (clear-stream $_test-input-buffered-file->buffer)
 8359     (clear-stream _test-output-stream)
 8360     (clear-stream $_test-output-buffered-file->buffer)
 8361     (clear-stream _test-error-stream)
 8362     (clear-stream $_test-error-buffered-file->buffer)
 8363     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8364     68/push 0/imm32
 8365     68/push 0/imm32
 8366     89/<- %edx 4/r32/esp
 8367     (tailor-exit-descriptor %edx 0x10)
 8368     #
 8369     (write _test-input-stream "fn foo {\n")
 8370     (write _test-input-stream "  var a: (handle int)\n")
 8371     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 8372     (write _test-input-stream "}\n")
 8373     # convert
 8374     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8375     # registers except esp clobbered at this point
 8376     # restore ed
 8377     89/<- %edx 4/r32/esp
 8378     (flush _test-output-buffered-file)
 8379     (flush _test-error-buffered-file)
 8380 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8386     # check output
 8387     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
 8388     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type: error message")
 8389     # check that stop(1) was called
 8390     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
 8391     # don't restore from ebp
 8392     81 0/subop/add %esp 8/imm32
 8393     # . epilogue
 8394     5d/pop-to-ebp
 8395     c3/return
 8396 
 8397 test-compute-offset-with-non-array-compound-base-type-2:
 8398     # . prologue
 8399     55/push-ebp
 8400     89/<- %ebp 4/r32/esp
 8401     # setup
 8402     (clear-stream _test-input-stream)
 8403     (clear-stream $_test-input-buffered-file->buffer)
 8404     (clear-stream _test-output-stream)
 8405     (clear-stream $_test-output-buffered-file->buffer)
 8406     (clear-stream _test-error-stream)
 8407     (clear-stream $_test-error-buffered-file->buffer)
 8408     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8409     68/push 0/imm32
 8410     68/push 0/imm32
 8411     89/<- %edx 4/r32/esp
 8412     (tailor-exit-descriptor %edx 0x10)
 8413     #
 8414     (write _test-input-stream "fn foo {\n")
 8415     (write _test-input-stream "  var a: (addr int)\n")
 8416     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 8417     (write _test-input-stream "}\n")
 8418     # convert
 8419     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8420     # registers except esp clobbered at this point
 8421     # restore ed
 8422     89/<- %edx 4/r32/esp
 8423     (flush _test-output-buffered-file)
 8424     (flush _test-error-buffered-file)
 8425 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8431     # check output
 8432     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
 8433     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type-2: error message")
 8434     # check that stop(1) was called
 8435     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
 8436     # don't restore from ebp
 8437     81 0/subop/add %esp 8/imm32
 8438     # . epilogue
 8439     5d/pop-to-ebp
 8440     c3/return
 8441 
 8442 test-compute-offset-with-array-atom-base-type:
 8443     # . prologue
 8444     55/push-ebp
 8445     89/<- %ebp 4/r32/esp
 8446     # setup
 8447     (clear-stream _test-input-stream)
 8448     (clear-stream $_test-input-buffered-file->buffer)
 8449     (clear-stream _test-output-stream)
 8450     (clear-stream $_test-output-buffered-file->buffer)
 8451     (clear-stream _test-error-stream)
 8452     (clear-stream $_test-error-buffered-file->buffer)
 8453     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8454     68/push 0/imm32
 8455     68/push 0/imm32
 8456     89/<- %edx 4/r32/esp
 8457     (tailor-exit-descriptor %edx 0x10)
 8458     #
 8459     (write _test-input-stream "fn foo {\n")
 8460     (write _test-input-stream "  var a: array\n")
 8461     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 8462     (write _test-input-stream "}\n")
 8463     # convert
 8464     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8465     # registers except esp clobbered at this point
 8466     # restore ed
 8467     89/<- %edx 4/r32/esp
 8468     (flush _test-output-buffered-file)
 8469     (flush _test-error-buffered-file)
 8470 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8476     # check output
 8477     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
 8478     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: array 'a' must specify the type of its elements"  "F - test-compute-offset-with-array-atom-base-type: error message")
 8479     # check that stop(1) was called
 8480     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
 8481     # don't restore from ebp
 8482     81 0/subop/add %esp 8/imm32
 8483     # . epilogue
 8484     5d/pop-to-ebp
 8485     c3/return
 8486 
 8487 test-compute-offset-with-wrong-index-type:
 8488     # . prologue
 8489     55/push-ebp
 8490     89/<- %ebp 4/r32/esp
 8491     # setup
 8492     (clear-stream _test-input-stream)
 8493     (clear-stream $_test-input-buffered-file->buffer)
 8494     (clear-stream _test-output-stream)
 8495     (clear-stream $_test-output-buffered-file->buffer)
 8496     (clear-stream _test-error-stream)
 8497     (clear-stream $_test-error-buffered-file->buffer)
 8498     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8499     68/push 0/imm32
 8500     68/push 0/imm32
 8501     89/<- %edx 4/r32/esp
 8502     (tailor-exit-descriptor %edx 0x10)
 8503     #
 8504     (write _test-input-stream "fn foo {\n")
 8505     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 8506     (write _test-input-stream "  var b: boolean\n")
 8507     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
 8508     (write _test-input-stream "}\n")
 8509     # convert
 8510     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8511     # registers except esp clobbered at this point
 8512     # restore ed
 8513     89/<- %edx 4/r32/esp
 8514     (flush _test-output-buffered-file)
 8515     (flush _test-error-buffered-file)
 8516 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8522     # check output
 8523     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
 8524     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: second argument 'b' must be an int"  "F - test-compute-offset-with-wrong-index-type: error message")
 8525     # check that stop(1) was called
 8526     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
 8527     # don't restore from ebp
 8528     81 0/subop/add %esp 8/imm32
 8529     # . epilogue
 8530     5d/pop-to-ebp
 8531     c3/return
 8532 
 8533 test-compute-offset-with-output-not-offset:
 8534     # . prologue
 8535     55/push-ebp
 8536     89/<- %ebp 4/r32/esp
 8537     # setup
 8538     (clear-stream _test-input-stream)
 8539     (clear-stream $_test-input-buffered-file->buffer)
 8540     (clear-stream _test-output-stream)
 8541     (clear-stream $_test-output-buffered-file->buffer)
 8542     (clear-stream _test-error-stream)
 8543     (clear-stream $_test-error-buffered-file->buffer)
 8544     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8545     68/push 0/imm32
 8546     68/push 0/imm32
 8547     89/<- %edx 4/r32/esp
 8548     (tailor-exit-descriptor %edx 0x10)
 8549     #
 8550     (write _test-input-stream "fn foo {\n")
 8551     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8552     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
 8553     (write _test-input-stream "}\n")
 8554     # convert
 8555     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8556     # registers except esp clobbered at this point
 8557     # restore ed
 8558     89/<- %edx 4/r32/esp
 8559     (flush _test-output-buffered-file)
 8560     (flush _test-error-buffered-file)
 8561 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8567     # check output
 8568     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
 8569     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-offset: error message")
 8570     # check that stop(1) was called
 8571     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
 8572     # don't restore from ebp
 8573     81 0/subop/add %esp 8/imm32
 8574     # . epilogue
 8575     5d/pop-to-ebp
 8576     c3/return
 8577 
 8578 test-compute-offset-with-output-not-address-2:
 8579     # . prologue
 8580     55/push-ebp
 8581     89/<- %ebp 4/r32/esp
 8582     # setup
 8583     (clear-stream _test-input-stream)
 8584     (clear-stream $_test-input-buffered-file->buffer)
 8585     (clear-stream _test-output-stream)
 8586     (clear-stream $_test-output-buffered-file->buffer)
 8587     (clear-stream _test-error-stream)
 8588     (clear-stream $_test-error-buffered-file->buffer)
 8589     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8590     68/push 0/imm32
 8591     68/push 0/imm32
 8592     89/<- %edx 4/r32/esp
 8593     (tailor-exit-descriptor %edx 0x10)
 8594     #
 8595     (write _test-input-stream "fn foo {\n")
 8596     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8597     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
 8598     (write _test-input-stream "}\n")
 8599     # convert
 8600     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8601     # registers except esp clobbered at this point
 8602     # restore ed
 8603     89/<- %edx 4/r32/esp
 8604     (flush _test-output-buffered-file)
 8605     (flush _test-error-buffered-file)
 8606 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8612     # check output
 8613     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
 8614     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-address-2: error message")
 8615     # check that stop(1) was called
 8616     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
 8617     # don't restore from ebp
 8618     81 0/subop/add %esp 8/imm32
 8619     # . epilogue
 8620     5d/pop-to-ebp
 8621     c3/return
 8622 
 8623 test-compute-offset-with-wrong-output-type:
 8624     # . prologue
 8625     55/push-ebp
 8626     89/<- %ebp 4/r32/esp
 8627     # setup
 8628     (clear-stream _test-input-stream)
 8629     (clear-stream $_test-input-buffered-file->buffer)
 8630     (clear-stream _test-output-stream)
 8631     (clear-stream $_test-output-buffered-file->buffer)
 8632     (clear-stream _test-error-stream)
 8633     (clear-stream $_test-error-buffered-file->buffer)
 8634     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8635     68/push 0/imm32
 8636     68/push 0/imm32
 8637     89/<- %edx 4/r32/esp
 8638     (tailor-exit-descriptor %edx 0x10)
 8639     #
 8640     (write _test-input-stream "fn foo {\n")
 8641     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8642     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
 8643     (write _test-input-stream "}\n")
 8644     # convert
 8645     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8646     # registers except esp clobbered at this point
 8647     # restore ed
 8648     89/<- %edx 4/r32/esp
 8649     (flush _test-output-buffered-file)
 8650     (flush _test-error-buffered-file)
 8651 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8657     # check output
 8658     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
 8659     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-type: error message")
 8660     # check that stop(1) was called
 8661     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
 8662     # don't restore from ebp
 8663     81 0/subop/add %esp 8/imm32
 8664     # . epilogue
 8665     5d/pop-to-ebp
 8666     c3/return
 8667 
 8668 test-compute-offset-with-wrong-output-compound-type:
 8669     # . prologue
 8670     55/push-ebp
 8671     89/<- %ebp 4/r32/esp
 8672     # setup
 8673     (clear-stream _test-input-stream)
 8674     (clear-stream $_test-input-buffered-file->buffer)
 8675     (clear-stream _test-output-stream)
 8676     (clear-stream $_test-output-buffered-file->buffer)
 8677     (clear-stream _test-error-stream)
 8678     (clear-stream $_test-error-buffered-file->buffer)
 8679     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8680     68/push 0/imm32
 8681     68/push 0/imm32
 8682     89/<- %edx 4/r32/esp
 8683     (tailor-exit-descriptor %edx 0x10)
 8684     #
 8685     (write _test-input-stream "fn foo {\n")
 8686     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 8687     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
 8688     (write _test-input-stream "}\n")
 8689     # convert
 8690     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8691     # registers except esp clobbered at this point
 8692     # restore ed
 8693     89/<- %edx 4/r32/esp
 8694     (flush _test-output-buffered-file)
 8695     (flush _test-error-buffered-file)
 8696 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8702     # check output
 8703     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
 8704     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-compound-type: error message")
 8705     # check that stop(1) was called
 8706     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
 8707     # don't restore from ebp
 8708     81 0/subop/add %esp 8/imm32
 8709     # . epilogue
 8710     5d/pop-to-ebp
 8711     c3/return
 8712 
 8713 test-compute-offset-with-no-inouts:
 8714     # . prologue
 8715     55/push-ebp
 8716     89/<- %ebp 4/r32/esp
 8717     # setup
 8718     (clear-stream _test-input-stream)
 8719     (clear-stream $_test-input-buffered-file->buffer)
 8720     (clear-stream _test-output-stream)
 8721     (clear-stream $_test-output-buffered-file->buffer)
 8722     (clear-stream _test-error-stream)
 8723     (clear-stream $_test-error-buffered-file->buffer)
 8724     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8725     68/push 0/imm32
 8726     68/push 0/imm32
 8727     89/<- %edx 4/r32/esp
 8728     (tailor-exit-descriptor %edx 0x10)
 8729     #
 8730     (write _test-input-stream "fn foo {\n")
 8731     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
 8732     (write _test-input-stream "}\n")
 8733     # convert
 8734     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8735     # registers except esp clobbered at this point
 8736     # restore ed
 8737     89/<- %edx 4/r32/esp
 8738     (flush _test-output-buffered-file)
 8739     (flush _test-error-buffered-file)
 8740 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8746     # check output
 8747     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
 8748     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-no-inouts: error message")
 8749     # check that stop(1) was called
 8750     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
 8751     # don't restore from ebp
 8752     81 0/subop/add %esp 8/imm32
 8753     # . epilogue
 8754     5d/pop-to-ebp
 8755     c3/return
 8756 
 8757 test-compute-offset-with-too-few-inouts:
 8758     # . prologue
 8759     55/push-ebp
 8760     89/<- %ebp 4/r32/esp
 8761     # setup
 8762     (clear-stream _test-input-stream)
 8763     (clear-stream $_test-input-buffered-file->buffer)
 8764     (clear-stream _test-output-stream)
 8765     (clear-stream $_test-output-buffered-file->buffer)
 8766     (clear-stream _test-error-stream)
 8767     (clear-stream $_test-error-buffered-file->buffer)
 8768     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8769     68/push 0/imm32
 8770     68/push 0/imm32
 8771     89/<- %edx 4/r32/esp
 8772     (tailor-exit-descriptor %edx 0x10)
 8773     #
 8774     (write _test-input-stream "fn foo {\n")
 8775     (write _test-input-stream "  var a: (array int 3)\n")
 8776     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
 8777     (write _test-input-stream "}\n")
 8778     # convert
 8779     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8780     # registers except esp clobbered at this point
 8781     # restore ed
 8782     89/<- %edx 4/r32/esp
 8783     (flush _test-output-buffered-file)
 8784     (flush _test-error-buffered-file)
 8785 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8791     # check output
 8792     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
 8793     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-too-few-inouts: error message")
 8794     # check that stop(1) was called
 8795     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
 8796     # don't restore from ebp
 8797     81 0/subop/add %esp 8/imm32
 8798     # . epilogue
 8799     5d/pop-to-ebp
 8800     c3/return
 8801 
 8802 test-compute-offset-with-too-many-inouts:
 8803     # . prologue
 8804     55/push-ebp
 8805     89/<- %ebp 4/r32/esp
 8806     # setup
 8807     (clear-stream _test-input-stream)
 8808     (clear-stream $_test-input-buffered-file->buffer)
 8809     (clear-stream _test-output-stream)
 8810     (clear-stream $_test-output-buffered-file->buffer)
 8811     (clear-stream _test-error-stream)
 8812     (clear-stream $_test-error-buffered-file->buffer)
 8813     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8814     68/push 0/imm32
 8815     68/push 0/imm32
 8816     89/<- %edx 4/r32/esp
 8817     (tailor-exit-descriptor %edx 0x10)
 8818     #
 8819     (write _test-input-stream "fn foo {\n")
 8820     (write _test-input-stream "  var a: (array int 3)\n")
 8821     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
 8822     (write _test-input-stream "}\n")
 8823     # convert
 8824     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8825     # registers except esp clobbered at this point
 8826     # restore ed
 8827     89/<- %edx 4/r32/esp
 8828     (flush _test-output-buffered-file)
 8829     (flush _test-error-buffered-file)
 8830 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8836     # check output
 8837     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
 8838     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many inouts (2 required)"  "F - test-compute-offset-with-too-many-inouts: error message")
 8839     # check that stop(1) was called
 8840     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
 8841     # don't restore from ebp
 8842     81 0/subop/add %esp 8/imm32
 8843     # . epilogue
 8844     5d/pop-to-ebp
 8845     c3/return
 8846 
 8847 test-compute-offset-with-no-output:
 8848     # . prologue
 8849     55/push-ebp
 8850     89/<- %ebp 4/r32/esp
 8851     # setup
 8852     (clear-stream _test-input-stream)
 8853     (clear-stream $_test-input-buffered-file->buffer)
 8854     (clear-stream _test-output-stream)
 8855     (clear-stream $_test-output-buffered-file->buffer)
 8856     (clear-stream _test-error-stream)
 8857     (clear-stream $_test-error-buffered-file->buffer)
 8858     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8859     68/push 0/imm32
 8860     68/push 0/imm32
 8861     89/<- %edx 4/r32/esp
 8862     (tailor-exit-descriptor %edx 0x10)
 8863     #
 8864     (write _test-input-stream "fn foo {\n")
 8865     (write _test-input-stream "  var a: (array int 3)\n")
 8866     (write _test-input-stream "  compute-offset a, 0\n")
 8867     (write _test-input-stream "}\n")
 8868     # convert
 8869     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8870     # registers except esp clobbered at this point
 8871     # restore ed
 8872     89/<- %edx 4/r32/esp
 8873     (flush _test-output-buffered-file)
 8874     (flush _test-error-buffered-file)
 8875 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8881     # check output
 8882     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
 8883     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: must have an output"  "F - test-compute-offset-with-no-output: error message")
 8884     # check that stop(1) was called
 8885     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
 8886     # don't restore from ebp
 8887     81 0/subop/add %esp 8/imm32
 8888     # . epilogue
 8889     5d/pop-to-ebp
 8890     c3/return
 8891 
 8892 test-compute-offset-with-too-many-outputs:
 8893     # . prologue
 8894     55/push-ebp
 8895     89/<- %ebp 4/r32/esp
 8896     # setup
 8897     (clear-stream _test-input-stream)
 8898     (clear-stream $_test-input-buffered-file->buffer)
 8899     (clear-stream _test-output-stream)
 8900     (clear-stream $_test-output-buffered-file->buffer)
 8901     (clear-stream _test-error-stream)
 8902     (clear-stream $_test-error-buffered-file->buffer)
 8903     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8904     68/push 0/imm32
 8905     68/push 0/imm32
 8906     89/<- %edx 4/r32/esp
 8907     (tailor-exit-descriptor %edx 0x10)
 8908     #
 8909     (write _test-input-stream "fn foo {\n")
 8910     (write _test-input-stream "  var a: (array int 3)\n")
 8911     (write _test-input-stream "  var b/eax: (offset int) <- copy 0\n")
 8912     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
 8913     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
 8914     (write _test-input-stream "}\n")
 8915     # convert
 8916     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8917     # registers except esp clobbered at this point
 8918     # restore ed
 8919     89/<- %edx 4/r32/esp
 8920     (flush _test-output-buffered-file)
 8921     (flush _test-error-buffered-file)
 8922 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8928     # check output
 8929     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
 8930     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many outputs (1 required)"  "F - test-compute-offset-with-too-many-outputs: error message")
 8931     # check that stop(1) was called
 8932     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
 8933     # don't restore from ebp
 8934     81 0/subop/add %esp 8/imm32
 8935     # . epilogue
 8936     5d/pop-to-ebp
 8937     c3/return
 8938 
 8939 test-convert-read-from-stream:
 8940     # . prologue
 8941     55/push-ebp
 8942     89/<- %ebp 4/r32/esp
 8943     # setup
 8944     (clear-stream _test-input-stream)
 8945     (clear-stream $_test-input-buffered-file->buffer)
 8946     (clear-stream _test-output-stream)
 8947     (clear-stream $_test-output-buffered-file->buffer)
 8948     #
 8949     (write _test-input-stream "fn foo {\n")
 8950     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
 8951     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
 8952     (write _test-input-stream "  read-from-stream s, o\n")
 8953     (write _test-input-stream "}\n")
 8954     # convert
 8955     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8956     # registers except esp clobbered at this point
 8957     # restore ed
 8958     89/<- %edx 4/r32/esp
 8959     (flush _test-output-buffered-file)
 8960     (flush _test-error-buffered-file)
 8961 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 8967     # check output
 8968     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
 8969     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
 8970     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
 8971     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
 8972     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
 8973     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
 8974     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
 8975     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
 8976     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
 8977     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
 8978     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
 8979     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
 8980     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
 8981     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
 8982     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
 8983     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
 8984     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
 8985     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
 8986     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
 8987     # . epilogue
 8988     89/<- %esp 5/r32/ebp
 8989     5d/pop-to-ebp
 8990     c3/return
 8991 
 8992 test-convert-read-from-stream-with-correct-payload-size:
 8993     # . prologue
 8994     55/push-ebp
 8995     89/<- %ebp 4/r32/esp
 8996     # setup
 8997     (clear-stream _test-input-stream)
 8998     (clear-stream $_test-input-buffered-file->buffer)
 8999     (clear-stream _test-output-stream)
 9000     (clear-stream $_test-output-buffered-file->buffer)
 9001     #
 9002     (write _test-input-stream "fn foo {\n")
 9003     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
 9004     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
 9005     (write _test-input-stream "  read-from-stream s, o\n")
 9006     (write _test-input-stream "}\n")
 9007     # convert
 9008     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9009     # registers except esp clobbered at this point
 9010     # restore ed
 9011     89/<- %edx 4/r32/esp
 9012     (flush _test-output-buffered-file)
 9013     (flush _test-error-buffered-file)
 9014 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 9020     # check output
 9021     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
 9022     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
 9023     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
 9024     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
 9025     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
 9026     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
 9027     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
 9028     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/7")
 9029     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
 9030     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/9")
 9031     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000008)"  "F - test-convert-read-from-stream-with-correct-payload-size/10")
 9032     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
 9033     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
 9034     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
 9035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
 9036     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
 9037     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
 9038     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
 9039     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
 9040     # . epilogue
 9041     89/<- %esp 5/r32/ebp
 9042     5d/pop-to-ebp
 9043     c3/return
 9044 
 9045 test-read-from-stream-with-non-stream-atom-base-type:
 9046     # . prologue
 9047     55/push-ebp
 9048     89/<- %ebp 4/r32/esp
 9049     # setup
 9050     (clear-stream _test-input-stream)
 9051     (clear-stream $_test-input-buffered-file->buffer)
 9052     (clear-stream _test-output-stream)
 9053     (clear-stream $_test-output-buffered-file->buffer)
 9054     (clear-stream _test-error-stream)
 9055     (clear-stream $_test-error-buffered-file->buffer)
 9056     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9057     68/push 0/imm32
 9058     68/push 0/imm32
 9059     89/<- %edx 4/r32/esp
 9060     (tailor-exit-descriptor %edx 0x10)
 9061     #
 9062     (write _test-input-stream "fn foo {\n")
 9063     (write _test-input-stream "  var a: int\n")
 9064     (write _test-input-stream "  read-from-stream a, 0\n")
 9065     (write _test-input-stream "}\n")
 9066     # convert
 9067     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9068     # registers except esp clobbered at this point
 9069     # restore ed
 9070     89/<- %edx 4/r32/esp
 9071     (flush _test-output-buffered-file)
 9072     (flush _test-error-buffered-file)
 9073 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9079     # check output
 9080     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
 9081     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-atom-base-type: error message")
 9082     # check that stop(1) was called
 9083     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
 9084     # don't restore from ebp
 9085     81 0/subop/add %esp 8/imm32
 9086     # . epilogue
 9087     5d/pop-to-ebp
 9088     c3/return
 9089 
 9090 test-read-from-stream-with-non-stream-compound-base-type:
 9091     # . prologue
 9092     55/push-ebp
 9093     89/<- %ebp 4/r32/esp
 9094     # setup
 9095     (clear-stream _test-input-stream)
 9096     (clear-stream $_test-input-buffered-file->buffer)
 9097     (clear-stream _test-output-stream)
 9098     (clear-stream $_test-output-buffered-file->buffer)
 9099     (clear-stream _test-error-stream)
 9100     (clear-stream $_test-error-buffered-file->buffer)
 9101     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9102     68/push 0/imm32
 9103     68/push 0/imm32
 9104     89/<- %edx 4/r32/esp
 9105     (tailor-exit-descriptor %edx 0x10)
 9106     #
 9107     (write _test-input-stream "fn foo {\n")
 9108     (write _test-input-stream "  var a: (handle int)\n")
 9109     (write _test-input-stream "  read-from-stream a, 0\n")
 9110     (write _test-input-stream "}\n")
 9111     # convert
 9112     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9113     # registers except esp clobbered at this point
 9114     # restore ed
 9115     89/<- %edx 4/r32/esp
 9116     (flush _test-output-buffered-file)
 9117     (flush _test-error-buffered-file)
 9118 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9124     # check output
 9125     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
 9126     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type: error message")
 9127     # check that stop(1) was called
 9128     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
 9129     # don't restore from ebp
 9130     81 0/subop/add %esp 8/imm32
 9131     # . epilogue
 9132     5d/pop-to-ebp
 9133     c3/return
 9134 
 9135 test-read-from-stream-with-non-stream-compound-base-type-2:
 9136     # . prologue
 9137     55/push-ebp
 9138     89/<- %ebp 4/r32/esp
 9139     # setup
 9140     (clear-stream _test-input-stream)
 9141     (clear-stream $_test-input-buffered-file->buffer)
 9142     (clear-stream _test-output-stream)
 9143     (clear-stream $_test-output-buffered-file->buffer)
 9144     (clear-stream _test-error-stream)
 9145     (clear-stream $_test-error-buffered-file->buffer)
 9146     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9147     68/push 0/imm32
 9148     68/push 0/imm32
 9149     89/<- %edx 4/r32/esp
 9150     (tailor-exit-descriptor %edx 0x10)
 9151     #
 9152     (write _test-input-stream "fn foo {\n")
 9153     (write _test-input-stream "  var a: (addr int)\n")
 9154     (write _test-input-stream "  read-from-stream a, 0\n")
 9155     (write _test-input-stream "}\n")
 9156     # convert
 9157     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9158     # registers except esp clobbered at this point
 9159     # restore ed
 9160     89/<- %edx 4/r32/esp
 9161     (flush _test-output-buffered-file)
 9162     (flush _test-error-buffered-file)
 9163 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9169     # check output
 9170     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
 9171     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message")
 9172     # check that stop(1) was called
 9173     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
 9174     # don't restore from ebp
 9175     81 0/subop/add %esp 8/imm32
 9176     # . epilogue
 9177     5d/pop-to-ebp
 9178     c3/return
 9179 
 9180 test-read-from-stream-with-stream-atom-base-type:
 9181     # . prologue
 9182     55/push-ebp
 9183     89/<- %ebp 4/r32/esp
 9184     # setup
 9185     (clear-stream _test-input-stream)
 9186     (clear-stream $_test-input-buffered-file->buffer)
 9187     (clear-stream _test-output-stream)
 9188     (clear-stream $_test-output-buffered-file->buffer)
 9189     (clear-stream _test-error-stream)
 9190     (clear-stream $_test-error-buffered-file->buffer)
 9191     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9192     68/push 0/imm32
 9193     68/push 0/imm32
 9194     89/<- %edx 4/r32/esp
 9195     (tailor-exit-descriptor %edx 0x10)
 9196     #
 9197     (write _test-input-stream "fn foo {\n")
 9198     (write _test-input-stream "  var a: stream\n")
 9199     (write _test-input-stream "  read-from-stream a, 0\n")
 9200     (write _test-input-stream "}\n")
 9201     # convert
 9202     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9203     # registers except esp clobbered at this point
 9204     # restore ed
 9205     89/<- %edx 4/r32/esp
 9206     (flush _test-output-buffered-file)
 9207     (flush _test-error-buffered-file)
 9208 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9214     # check output
 9215     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
 9216     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-stream-atom-base-type: error message")
 9217     # check that stop(1) was called
 9218     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
 9219     # don't restore from ebp
 9220     81 0/subop/add %esp 8/imm32
 9221     # . epilogue
 9222     5d/pop-to-ebp
 9223     c3/return
 9224 
 9225 test-read-from-stream-with-wrong-index-type:
 9226     # . prologue
 9227     55/push-ebp
 9228     89/<- %ebp 4/r32/esp
 9229     # setup
 9230     (clear-stream _test-input-stream)
 9231     (clear-stream $_test-input-buffered-file->buffer)
 9232     (clear-stream _test-output-stream)
 9233     (clear-stream $_test-output-buffered-file->buffer)
 9234     (clear-stream _test-error-stream)
 9235     (clear-stream $_test-error-buffered-file->buffer)
 9236     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9237     68/push 0/imm32
 9238     68/push 0/imm32
 9239     89/<- %edx 4/r32/esp
 9240     (tailor-exit-descriptor %edx 0x10)
 9241     #
 9242     (write _test-input-stream "fn foo {\n")
 9243     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
 9244     (write _test-input-stream "  var b: boolean\n")
 9245     (write _test-input-stream "  read-from-stream a, b\n")
 9246     (write _test-input-stream "}\n")
 9247     # convert
 9248     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9249     # registers except esp clobbered at this point
 9250     # restore ed
 9251     89/<- %edx 4/r32/esp
 9252     (flush _test-output-buffered-file)
 9253     (flush _test-error-buffered-file)
 9254 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9260     # check output
 9261     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
 9262     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: target 'b' must be an addr"  "F - test-read-from-stream-with-wrong-index-type: error message")
 9263     # check that stop(1) was called
 9264     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
 9265     # don't restore from ebp
 9266     81 0/subop/add %esp 8/imm32
 9267     # . epilogue
 9268     5d/pop-to-ebp
 9269     c3/return
 9270 
 9271 test-read-from-stream-with-no-inouts:
 9272     # . prologue
 9273     55/push-ebp
 9274     89/<- %ebp 4/r32/esp
 9275     # setup
 9276     (clear-stream _test-input-stream)
 9277     (clear-stream $_test-input-buffered-file->buffer)
 9278     (clear-stream _test-output-stream)
 9279     (clear-stream $_test-output-buffered-file->buffer)
 9280     (clear-stream _test-error-stream)
 9281     (clear-stream $_test-error-buffered-file->buffer)
 9282     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9283     68/push 0/imm32
 9284     68/push 0/imm32
 9285     89/<- %edx 4/r32/esp
 9286     (tailor-exit-descriptor %edx 0x10)
 9287     #
 9288     (write _test-input-stream "fn foo {\n")
 9289     (write _test-input-stream "  read-from-stream\n")
 9290     (write _test-input-stream "}\n")
 9291     # convert
 9292     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9293     # registers except esp clobbered at this point
 9294     # restore ed
 9295     89/<- %edx 4/r32/esp
 9296     (flush _test-output-buffered-file)
 9297     (flush _test-error-buffered-file)
 9298 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9304     # check output
 9305     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
 9306     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-no-inouts: error message")
 9307     # check that stop(1) was called
 9308     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
 9309     # don't restore from ebp
 9310     81 0/subop/add %esp 8/imm32
 9311     # . epilogue
 9312     5d/pop-to-ebp
 9313     c3/return
 9314 
 9315 test-read-from-stream-with-too-few-inouts:
 9316     # . prologue
 9317     55/push-ebp
 9318     89/<- %ebp 4/r32/esp
 9319     # setup
 9320     (clear-stream _test-input-stream)
 9321     (clear-stream $_test-input-buffered-file->buffer)
 9322     (clear-stream _test-output-stream)
 9323     (clear-stream $_test-output-buffered-file->buffer)
 9324     (clear-stream _test-error-stream)
 9325     (clear-stream $_test-error-buffered-file->buffer)
 9326     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9327     68/push 0/imm32
 9328     68/push 0/imm32
 9329     89/<- %edx 4/r32/esp
 9330     (tailor-exit-descriptor %edx 0x10)
 9331     #
 9332     (write _test-input-stream "fn foo {\n")
 9333     (write _test-input-stream "  var a: (addr stream int)\n")
 9334     (write _test-input-stream "  read-from-stream a\n")
 9335     (write _test-input-stream "}\n")
 9336     # convert
 9337     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9338     # registers except esp clobbered at this point
 9339     # restore ed
 9340     89/<- %edx 4/r32/esp
 9341     (flush _test-output-buffered-file)
 9342     (flush _test-error-buffered-file)
 9343 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9349     # check output
 9350     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
 9351     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-too-few-inouts: error message")
 9352     # check that stop(1) was called
 9353     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
 9354     # don't restore from ebp
 9355     81 0/subop/add %esp 8/imm32
 9356     # . epilogue
 9357     5d/pop-to-ebp
 9358     c3/return
 9359 
 9360 test-read-from-stream-with-too-many-inouts:
 9361     # . prologue
 9362     55/push-ebp
 9363     89/<- %ebp 4/r32/esp
 9364     # setup
 9365     (clear-stream _test-input-stream)
 9366     (clear-stream $_test-input-buffered-file->buffer)
 9367     (clear-stream _test-output-stream)
 9368     (clear-stream $_test-output-buffered-file->buffer)
 9369     (clear-stream _test-error-stream)
 9370     (clear-stream $_test-error-buffered-file->buffer)
 9371     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9372     68/push 0/imm32
 9373     68/push 0/imm32
 9374     89/<- %edx 4/r32/esp
 9375     (tailor-exit-descriptor %edx 0x10)
 9376     #
 9377     (write _test-input-stream "fn foo {\n")
 9378     (write _test-input-stream "  var a: (addr stream int)\n")
 9379     (write _test-input-stream "  var b: (addr int)\n")
 9380     (write _test-input-stream "  read-from-stream a, b, 0\n")
 9381     (write _test-input-stream "}\n")
 9382     # convert
 9383     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9384     # registers except esp clobbered at this point
 9385     # restore ed
 9386     89/<- %edx 4/r32/esp
 9387     (flush _test-output-buffered-file)
 9388     (flush _test-error-buffered-file)
 9389 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9395     # check output
 9396     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
 9397     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too many inouts (2 required)"  "F - test-read-from-stream-with-too-many-inouts: error message")
 9398     # check that stop(1) was called
 9399     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
 9400     # don't restore from ebp
 9401     81 0/subop/add %esp 8/imm32
 9402     # . epilogue
 9403     5d/pop-to-ebp
 9404     c3/return
 9405 
 9406 test-read-from-stream-with-output:
 9407     # . prologue
 9408     55/push-ebp
 9409     89/<- %ebp 4/r32/esp
 9410     # setup
 9411     (clear-stream _test-input-stream)
 9412     (clear-stream $_test-input-buffered-file->buffer)
 9413     (clear-stream _test-output-stream)
 9414     (clear-stream $_test-output-buffered-file->buffer)
 9415     (clear-stream _test-error-stream)
 9416     (clear-stream $_test-error-buffered-file->buffer)
 9417     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9418     68/push 0/imm32
 9419     68/push 0/imm32
 9420     89/<- %edx 4/r32/esp
 9421     (tailor-exit-descriptor %edx 0x10)
 9422     #
 9423     (write _test-input-stream "fn foo {\n")
 9424     (write _test-input-stream "  var a: (addr stream int)\n")
 9425     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 9426     (write _test-input-stream "  b <- read-from-stream a, b\n")
 9427     (write _test-input-stream "}\n")
 9428     # convert
 9429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9430     # registers except esp clobbered at this point
 9431     # restore ed
 9432     89/<- %edx 4/r32/esp
 9433     (flush _test-output-buffered-file)
 9434     (flush _test-error-buffered-file)
 9435 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9441     # check output
 9442     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
 9443     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: unexpected output"  "F - test-read-from-stream-with-output: error message")
 9444     # check that stop(1) was called
 9445     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
 9446     # don't restore from ebp
 9447     81 0/subop/add %esp 8/imm32
 9448     # . epilogue
 9449     5d/pop-to-ebp
 9450     c3/return
 9451 
 9452 test-convert-write-to-stream:
 9453     # . prologue
 9454     55/push-ebp
 9455     89/<- %ebp 4/r32/esp
 9456     # setup
 9457     (clear-stream _test-input-stream)
 9458     (clear-stream $_test-input-buffered-file->buffer)
 9459     (clear-stream _test-output-stream)
 9460     (clear-stream $_test-output-buffered-file->buffer)
 9461     #
 9462     (write _test-input-stream "fn foo {\n")
 9463     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
 9464     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
 9465     (write _test-input-stream "  write-to-stream s, o\n")
 9466     (write _test-input-stream "}\n")
 9467     # convert
 9468     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9469     # registers except esp clobbered at this point
 9470     # restore ed
 9471     89/<- %edx 4/r32/esp
 9472     (flush _test-output-buffered-file)
 9473     (flush _test-error-buffered-file)
 9474 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 9480     # check output
 9481     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
 9482     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
 9483     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
 9484     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
 9485     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
 9486     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
 9487     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
 9488     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
 9489     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
 9490     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
 9491     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
 9492     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
 9493     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
 9494     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
 9495     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
 9496     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
 9497     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
 9498     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
 9499     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
 9500     # . epilogue
 9501     89/<- %esp 5/r32/ebp
 9502     5d/pop-to-ebp
 9503     c3/return
 9504 
 9505 test-convert-write-to-stream-with-correct-payload-size:
 9506     # . prologue
 9507     55/push-ebp
 9508     89/<- %ebp 4/r32/esp
 9509     # setup
 9510     (clear-stream _test-input-stream)
 9511     (clear-stream $_test-input-buffered-file->buffer)
 9512     (clear-stream _test-output-stream)
 9513     (clear-stream $_test-output-buffered-file->buffer)
 9514     #
 9515     (write _test-input-stream "fn foo {\n")
 9516     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
 9517     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
 9518     (write _test-input-stream "  write-to-stream s, o\n")
 9519     (write _test-input-stream "}\n")
 9520     # convert
 9521     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9522     # registers except esp clobbered at this point
 9523     # restore ed
 9524     89/<- %edx 4/r32/esp
 9525     (flush _test-output-buffered-file)
 9526     (flush _test-error-buffered-file)
 9527 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 9533     # check output
 9534     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
 9535     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
 9536     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
 9537     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
 9538     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
 9539     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
 9540     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
 9541     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/7")
 9542     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
 9543     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/9")
 9544     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000008)"  "F - test-convert-write-to-stream-with-correct-payload-size/10")
 9545     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
 9546     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
 9547     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
 9548     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
 9549     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
 9550     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
 9551     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
 9552     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
 9553     # . epilogue
 9554     89/<- %esp 5/r32/ebp
 9555     5d/pop-to-ebp
 9556     c3/return
 9557 
 9558 test-write-to-stream-with-non-stream-atom-base-type:
 9559     # . prologue
 9560     55/push-ebp
 9561     89/<- %ebp 4/r32/esp
 9562     # setup
 9563     (clear-stream _test-input-stream)
 9564     (clear-stream $_test-input-buffered-file->buffer)
 9565     (clear-stream _test-output-stream)
 9566     (clear-stream $_test-output-buffered-file->buffer)
 9567     (clear-stream _test-error-stream)
 9568     (clear-stream $_test-error-buffered-file->buffer)
 9569     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9570     68/push 0/imm32
 9571     68/push 0/imm32
 9572     89/<- %edx 4/r32/esp
 9573     (tailor-exit-descriptor %edx 0x10)
 9574     #
 9575     (write _test-input-stream "fn foo {\n")
 9576     (write _test-input-stream "  var a: int\n")
 9577     (write _test-input-stream "  write-to-stream a, 0\n")
 9578     (write _test-input-stream "}\n")
 9579     # convert
 9580     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9581     # registers except esp clobbered at this point
 9582     # restore ed
 9583     89/<- %edx 4/r32/esp
 9584     (flush _test-output-buffered-file)
 9585     (flush _test-error-buffered-file)
 9586 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9592     # check output
 9593     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
 9594     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-atom-base-type: error message")
 9595     # check that stop(1) was called
 9596     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
 9597     # don't restore from ebp
 9598     81 0/subop/add %esp 8/imm32
 9599     # . epilogue
 9600     5d/pop-to-ebp
 9601     c3/return
 9602 
 9603 test-write-to-stream-with-non-stream-compound-base-type:
 9604     # . prologue
 9605     55/push-ebp
 9606     89/<- %ebp 4/r32/esp
 9607     # setup
 9608     (clear-stream _test-input-stream)
 9609     (clear-stream $_test-input-buffered-file->buffer)
 9610     (clear-stream _test-output-stream)
 9611     (clear-stream $_test-output-buffered-file->buffer)
 9612     (clear-stream _test-error-stream)
 9613     (clear-stream $_test-error-buffered-file->buffer)
 9614     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9615     68/push 0/imm32
 9616     68/push 0/imm32
 9617     89/<- %edx 4/r32/esp
 9618     (tailor-exit-descriptor %edx 0x10)
 9619     #
 9620     (write _test-input-stream "fn foo {\n")
 9621     (write _test-input-stream "  var a: (handle int)\n")
 9622     (write _test-input-stream "  write-to-stream a, 0\n")
 9623     (write _test-input-stream "}\n")
 9624     # convert
 9625     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9626     # registers except esp clobbered at this point
 9627     # restore ed
 9628     89/<- %edx 4/r32/esp
 9629     (flush _test-output-buffered-file)
 9630     (flush _test-error-buffered-file)
 9631 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9637     # check output
 9638     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
 9639     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type: error message")
 9640     # check that stop(1) was called
 9641     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
 9642     # don't restore from ebp
 9643     81 0/subop/add %esp 8/imm32
 9644     # . epilogue
 9645     5d/pop-to-ebp
 9646     c3/return
 9647 
 9648 test-write-to-stream-with-non-stream-compound-base-type-2:
 9649     # . prologue
 9650     55/push-ebp
 9651     89/<- %ebp 4/r32/esp
 9652     # setup
 9653     (clear-stream _test-input-stream)
 9654     (clear-stream $_test-input-buffered-file->buffer)
 9655     (clear-stream _test-output-stream)
 9656     (clear-stream $_test-output-buffered-file->buffer)
 9657     (clear-stream _test-error-stream)
 9658     (clear-stream $_test-error-buffered-file->buffer)
 9659     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9660     68/push 0/imm32
 9661     68/push 0/imm32
 9662     89/<- %edx 4/r32/esp
 9663     (tailor-exit-descriptor %edx 0x10)
 9664     #
 9665     (write _test-input-stream "fn foo {\n")
 9666     (write _test-input-stream "  var a: (addr int)\n")
 9667     (write _test-input-stream "  write-to-stream a, 0\n")
 9668     (write _test-input-stream "}\n")
 9669     # convert
 9670     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9671     # registers except esp clobbered at this point
 9672     # restore ed
 9673     89/<- %edx 4/r32/esp
 9674     (flush _test-output-buffered-file)
 9675     (flush _test-error-buffered-file)
 9676 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9682     # check output
 9683     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
 9684     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message")
 9685     # check that stop(1) was called
 9686     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
 9687     # don't restore from ebp
 9688     81 0/subop/add %esp 8/imm32
 9689     # . epilogue
 9690     5d/pop-to-ebp
 9691     c3/return
 9692 
 9693 test-write-to-stream-with-stream-atom-base-type:
 9694     # . prologue
 9695     55/push-ebp
 9696     89/<- %ebp 4/r32/esp
 9697     # setup
 9698     (clear-stream _test-input-stream)
 9699     (clear-stream $_test-input-buffered-file->buffer)
 9700     (clear-stream _test-output-stream)
 9701     (clear-stream $_test-output-buffered-file->buffer)
 9702     (clear-stream _test-error-stream)
 9703     (clear-stream $_test-error-buffered-file->buffer)
 9704     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9705     68/push 0/imm32
 9706     68/push 0/imm32
 9707     89/<- %edx 4/r32/esp
 9708     (tailor-exit-descriptor %edx 0x10)
 9709     #
 9710     (write _test-input-stream "fn foo {\n")
 9711     (write _test-input-stream "  var a: stream\n")
 9712     (write _test-input-stream "  write-to-stream a, 0\n")
 9713     (write _test-input-stream "}\n")
 9714     # convert
 9715     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9716     # registers except esp clobbered at this point
 9717     # restore ed
 9718     89/<- %edx 4/r32/esp
 9719     (flush _test-output-buffered-file)
 9720     (flush _test-error-buffered-file)
 9721 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9727     # check output
 9728     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
 9729     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-stream-atom-base-type: error message")
 9730     # check that stop(1) was called
 9731     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
 9732     # don't restore from ebp
 9733     81 0/subop/add %esp 8/imm32
 9734     # . epilogue
 9735     5d/pop-to-ebp
 9736     c3/return
 9737 
 9738 test-write-to-stream-with-wrong-index-type:
 9739     # . prologue
 9740     55/push-ebp
 9741     89/<- %ebp 4/r32/esp
 9742     # setup
 9743     (clear-stream _test-input-stream)
 9744     (clear-stream $_test-input-buffered-file->buffer)
 9745     (clear-stream _test-output-stream)
 9746     (clear-stream $_test-output-buffered-file->buffer)
 9747     (clear-stream _test-error-stream)
 9748     (clear-stream $_test-error-buffered-file->buffer)
 9749     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9750     68/push 0/imm32
 9751     68/push 0/imm32
 9752     89/<- %edx 4/r32/esp
 9753     (tailor-exit-descriptor %edx 0x10)
 9754     #
 9755     (write _test-input-stream "fn foo {\n")
 9756     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
 9757     (write _test-input-stream "  var b: boolean\n")
 9758     (write _test-input-stream "  write-to-stream a, b\n")
 9759     (write _test-input-stream "}\n")
 9760     # convert
 9761     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9762     # registers except esp clobbered at this point
 9763     # restore ed
 9764     89/<- %edx 4/r32/esp
 9765     (flush _test-output-buffered-file)
 9766     (flush _test-error-buffered-file)
 9767 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9773     # check output
 9774     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
 9775     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: target 'b' must be an addr"  "F - test-write-to-stream-with-wrong-index-type: error message")
 9776     # check that stop(1) was called
 9777     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
 9778     # don't restore from ebp
 9779     81 0/subop/add %esp 8/imm32
 9780     # . epilogue
 9781     5d/pop-to-ebp
 9782     c3/return
 9783 
 9784 test-write-to-stream-with-no-inouts:
 9785     # . prologue
 9786     55/push-ebp
 9787     89/<- %ebp 4/r32/esp
 9788     # setup
 9789     (clear-stream _test-input-stream)
 9790     (clear-stream $_test-input-buffered-file->buffer)
 9791     (clear-stream _test-output-stream)
 9792     (clear-stream $_test-output-buffered-file->buffer)
 9793     (clear-stream _test-error-stream)
 9794     (clear-stream $_test-error-buffered-file->buffer)
 9795     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9796     68/push 0/imm32
 9797     68/push 0/imm32
 9798     89/<- %edx 4/r32/esp
 9799     (tailor-exit-descriptor %edx 0x10)
 9800     #
 9801     (write _test-input-stream "fn foo {\n")
 9802     (write _test-input-stream "  write-to-stream\n")
 9803     (write _test-input-stream "}\n")
 9804     # convert
 9805     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9806     # registers except esp clobbered at this point
 9807     # restore ed
 9808     89/<- %edx 4/r32/esp
 9809     (flush _test-output-buffered-file)
 9810     (flush _test-error-buffered-file)
 9811 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9817     # check output
 9818     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
 9819     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-no-inouts: error message")
 9820     # check that stop(1) was called
 9821     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
 9822     # don't restore from ebp
 9823     81 0/subop/add %esp 8/imm32
 9824     # . epilogue
 9825     5d/pop-to-ebp
 9826     c3/return
 9827 
 9828 test-write-to-stream-with-too-few-inouts:
 9829     # . prologue
 9830     55/push-ebp
 9831     89/<- %ebp 4/r32/esp
 9832     # setup
 9833     (clear-stream _test-input-stream)
 9834     (clear-stream $_test-input-buffered-file->buffer)
 9835     (clear-stream _test-output-stream)
 9836     (clear-stream $_test-output-buffered-file->buffer)
 9837     (clear-stream _test-error-stream)
 9838     (clear-stream $_test-error-buffered-file->buffer)
 9839     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9840     68/push 0/imm32
 9841     68/push 0/imm32
 9842     89/<- %edx 4/r32/esp
 9843     (tailor-exit-descriptor %edx 0x10)
 9844     #
 9845     (write _test-input-stream "fn foo {\n")
 9846     (write _test-input-stream "  var a: (addr stream int)\n")
 9847     (write _test-input-stream "  write-to-stream a\n")
 9848     (write _test-input-stream "}\n")
 9849     # convert
 9850     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9851     # registers except esp clobbered at this point
 9852     # restore ed
 9853     89/<- %edx 4/r32/esp
 9854     (flush _test-output-buffered-file)
 9855     (flush _test-error-buffered-file)
 9856 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9862     # check output
 9863     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
 9864     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-too-few-inouts: error message")
 9865     # check that stop(1) was called
 9866     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
 9867     # don't restore from ebp
 9868     81 0/subop/add %esp 8/imm32
 9869     # . epilogue
 9870     5d/pop-to-ebp
 9871     c3/return
 9872 
 9873 test-write-to-stream-with-too-many-inouts:
 9874     # . prologue
 9875     55/push-ebp
 9876     89/<- %ebp 4/r32/esp
 9877     # setup
 9878     (clear-stream _test-input-stream)
 9879     (clear-stream $_test-input-buffered-file->buffer)
 9880     (clear-stream _test-output-stream)
 9881     (clear-stream $_test-output-buffered-file->buffer)
 9882     (clear-stream _test-error-stream)
 9883     (clear-stream $_test-error-buffered-file->buffer)
 9884     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9885     68/push 0/imm32
 9886     68/push 0/imm32
 9887     89/<- %edx 4/r32/esp
 9888     (tailor-exit-descriptor %edx 0x10)
 9889     #
 9890     (write _test-input-stream "fn foo {\n")
 9891     (write _test-input-stream "  var a: (addr stream int)\n")
 9892     (write _test-input-stream "  var b: (addr int)\n")
 9893     (write _test-input-stream "  write-to-stream a, b, 0\n")
 9894     (write _test-input-stream "}\n")
 9895     # convert
 9896     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9897     # registers except esp clobbered at this point
 9898     # restore ed
 9899     89/<- %edx 4/r32/esp
 9900     (flush _test-output-buffered-file)
 9901     (flush _test-error-buffered-file)
 9902 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9908     # check output
 9909     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
 9910     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too many inouts (2 required)"  "F - test-write-to-stream-with-too-many-inouts: error message")
 9911     # check that stop(1) was called
 9912     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
 9913     # don't restore from ebp
 9914     81 0/subop/add %esp 8/imm32
 9915     # . epilogue
 9916     5d/pop-to-ebp
 9917     c3/return
 9918 
 9919 test-write-to-stream-with-output:
 9920     # . prologue
 9921     55/push-ebp
 9922     89/<- %ebp 4/r32/esp
 9923     # setup
 9924     (clear-stream _test-input-stream)
 9925     (clear-stream $_test-input-buffered-file->buffer)
 9926     (clear-stream _test-output-stream)
 9927     (clear-stream $_test-output-buffered-file->buffer)
 9928     (clear-stream _test-error-stream)
 9929     (clear-stream $_test-error-buffered-file->buffer)
 9930     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9931     68/push 0/imm32
 9932     68/push 0/imm32
 9933     89/<- %edx 4/r32/esp
 9934     (tailor-exit-descriptor %edx 0x10)
 9935     #
 9936     (write _test-input-stream "fn foo {\n")
 9937     (write _test-input-stream "  var a: (addr stream int)\n")
 9938     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 9939     (write _test-input-stream "  b <- write-to-stream a, b\n")
 9940     (write _test-input-stream "}\n")
 9941     # convert
 9942     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9943     # registers except esp clobbered at this point
 9944     # restore ed
 9945     89/<- %edx 4/r32/esp
 9946     (flush _test-output-buffered-file)
 9947     (flush _test-error-buffered-file)
 9948 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9954     # check output
 9955     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
 9956     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: unexpected output"  "F - test-write-to-stream-with-output: error message")
 9957     # check that stop(1) was called
 9958     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
 9959     # don't restore from ebp
 9960     81 0/subop/add %esp 8/imm32
 9961     # . epilogue
 9962     5d/pop-to-ebp
 9963     c3/return
 9964 
 9965 test-length-with-non-array-atom-base-type:
 9966     # . prologue
 9967     55/push-ebp
 9968     89/<- %ebp 4/r32/esp
 9969     # setup
 9970     (clear-stream _test-input-stream)
 9971     (clear-stream $_test-input-buffered-file->buffer)
 9972     (clear-stream _test-output-stream)
 9973     (clear-stream $_test-output-buffered-file->buffer)
 9974     (clear-stream _test-error-stream)
 9975     (clear-stream $_test-error-buffered-file->buffer)
 9976     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9977     68/push 0/imm32
 9978     68/push 0/imm32
 9979     89/<- %edx 4/r32/esp
 9980     (tailor-exit-descriptor %edx 0x10)
 9981     #
 9982     (write _test-input-stream "fn foo {\n")
 9983     (write _test-input-stream "  var a: int\n")
 9984     (write _test-input-stream "  var c/ecx: int <- length a\n")
 9985     (write _test-input-stream "}\n")
 9986     # convert
 9987     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9988     # registers except esp clobbered at this point
 9989     # restore ed
 9990     89/<- %edx 4/r32/esp
 9991     (flush _test-output-buffered-file)
 9992     (flush _test-error-buffered-file)
 9993 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9999     # check output
10000     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
10001     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-atom-base-type: error message")
10002     # check that stop(1) was called
10003     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
10004     # don't restore from ebp
10005     81 0/subop/add %esp 8/imm32
10006     # . epilogue
10007     5d/pop-to-ebp
10008     c3/return
10009 
10010 test-length-with-non-array-compound-base-type:
10011     # . prologue
10012     55/push-ebp
10013     89/<- %ebp 4/r32/esp
10014     # setup
10015     (clear-stream _test-input-stream)
10016     (clear-stream $_test-input-buffered-file->buffer)
10017     (clear-stream _test-output-stream)
10018     (clear-stream $_test-output-buffered-file->buffer)
10019     (clear-stream _test-error-stream)
10020     (clear-stream $_test-error-buffered-file->buffer)
10021     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10022     68/push 0/imm32
10023     68/push 0/imm32
10024     89/<- %edx 4/r32/esp
10025     (tailor-exit-descriptor %edx 0x10)
10026     #
10027     (write _test-input-stream "fn foo {\n")
10028     (write _test-input-stream "  var a: (handle int)\n")
10029     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
10030     (write _test-input-stream "}\n")
10031     # convert
10032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10033     # registers except esp clobbered at this point
10034     # restore ed
10035     89/<- %edx 4/r32/esp
10036     (flush _test-output-buffered-file)
10037     (flush _test-error-buffered-file)
10038 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10044     # check output
10045     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
10046     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type: error message")
10047     # check that stop(1) was called
10048     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
10049     # don't restore from ebp
10050     81 0/subop/add %esp 8/imm32
10051     # . epilogue
10052     5d/pop-to-ebp
10053     c3/return
10054 
10055 test-length-with-non-array-compound-base-type-2:
10056     # . prologue
10057     55/push-ebp
10058     89/<- %ebp 4/r32/esp
10059     # setup
10060     (clear-stream _test-input-stream)
10061     (clear-stream $_test-input-buffered-file->buffer)
10062     (clear-stream _test-output-stream)
10063     (clear-stream $_test-output-buffered-file->buffer)
10064     (clear-stream _test-error-stream)
10065     (clear-stream $_test-error-buffered-file->buffer)
10066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10067     68/push 0/imm32
10068     68/push 0/imm32
10069     89/<- %edx 4/r32/esp
10070     (tailor-exit-descriptor %edx 0x10)
10071     #
10072     (write _test-input-stream "fn foo {\n")
10073     (write _test-input-stream "  var a: (addr int)\n")
10074     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
10075     (write _test-input-stream "}\n")
10076     # convert
10077     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10078     # registers except esp clobbered at this point
10079     # restore ed
10080     89/<- %edx 4/r32/esp
10081     (flush _test-output-buffered-file)
10082     (flush _test-error-buffered-file)
10083 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10089     # check output
10090     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
10091     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type-2: error message")
10092     # check that stop(1) was called
10093     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
10094     # don't restore from ebp
10095     81 0/subop/add %esp 8/imm32
10096     # . epilogue
10097     5d/pop-to-ebp
10098     c3/return
10099 
10100 test-length-with-array-atom-base-type:
10101     # . prologue
10102     55/push-ebp
10103     89/<- %ebp 4/r32/esp
10104     # setup
10105     (clear-stream _test-input-stream)
10106     (clear-stream $_test-input-buffered-file->buffer)
10107     (clear-stream _test-output-stream)
10108     (clear-stream $_test-output-buffered-file->buffer)
10109     (clear-stream _test-error-stream)
10110     (clear-stream $_test-error-buffered-file->buffer)
10111     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10112     68/push 0/imm32
10113     68/push 0/imm32
10114     89/<- %edx 4/r32/esp
10115     (tailor-exit-descriptor %edx 0x10)
10116     #
10117     (write _test-input-stream "fn foo {\n")
10118     (write _test-input-stream "  var a: array\n")
10119     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
10120     (write _test-input-stream "}\n")
10121     # convert
10122     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10123     # registers except esp clobbered at this point
10124     # restore ed
10125     89/<- %edx 4/r32/esp
10126     (flush _test-output-buffered-file)
10127     (flush _test-error-buffered-file)
10128 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10134     # check output
10135     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
10136     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: array 'a' must specify the type of its elements"  "F - test-length-with-array-atom-base-type: error message")
10137     # check that stop(1) was called
10138     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
10139     # don't restore from ebp
10140     81 0/subop/add %esp 8/imm32
10141     # . epilogue
10142     5d/pop-to-ebp
10143     c3/return
10144 
10145 test-length-with-addr-base-on-stack:
10146     # . prologue
10147     55/push-ebp
10148     89/<- %ebp 4/r32/esp
10149     # setup
10150     (clear-stream _test-input-stream)
10151     (clear-stream $_test-input-buffered-file->buffer)
10152     (clear-stream _test-output-stream)
10153     (clear-stream $_test-output-buffered-file->buffer)
10154     (clear-stream _test-error-stream)
10155     (clear-stream $_test-error-buffered-file->buffer)
10156     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10157     68/push 0/imm32
10158     68/push 0/imm32
10159     89/<- %edx 4/r32/esp
10160     (tailor-exit-descriptor %edx 0x10)
10161     #
10162     (write _test-input-stream "fn foo {\n")
10163     (write _test-input-stream "  var a: (addr array int)\n")
10164     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
10165     (write _test-input-stream "}\n")
10166     # convert
10167     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10168     # registers except esp clobbered at this point
10169     # restore ed
10170     89/<- %edx 4/r32/esp
10171     (flush _test-output-buffered-file)
10172     (flush _test-error-buffered-file)
10173 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10179     # check output
10180     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
10181     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is an addr to an array, and so must live in a register"  "F - test-length-with-addr-base-on-stack: error message")
10182     # check that stop(1) was called
10183     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
10184     # don't restore from ebp
10185     81 0/subop/add %esp 8/imm32
10186     # . epilogue
10187     5d/pop-to-ebp
10188     c3/return
10189 
10190 test-length-with-array-base-in-register:
10191     # . prologue
10192     55/push-ebp
10193     89/<- %ebp 4/r32/esp
10194     # setup
10195     (clear-stream _test-input-stream)
10196     (clear-stream $_test-input-buffered-file->buffer)
10197     (clear-stream _test-output-stream)
10198     (clear-stream $_test-output-buffered-file->buffer)
10199     (clear-stream _test-error-stream)
10200     (clear-stream $_test-error-buffered-file->buffer)
10201     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10202     68/push 0/imm32
10203     68/push 0/imm32
10204     89/<- %edx 4/r32/esp
10205     (tailor-exit-descriptor %edx 0x10)
10206     #
10207     (write _test-input-stream "fn foo {\n")
10208     (write _test-input-stream "  var a/eax: (array int 3) <- copy 0\n")
10209     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
10210     (write _test-input-stream "}\n")
10211     # convert
10212     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10213     # registers except esp clobbered at this point
10214     # restore ed
10215     89/<- %edx 4/r32/esp
10216     (flush _test-output-buffered-file)
10217     (flush _test-error-buffered-file)
10218 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10224     # check output
10225     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-base-in-register: output should be empty")
10226     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is an array, and so must live on the stack"  "F - test-length-with-array-base-in-register: error message")
10227     # check that stop(1) was called
10228     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-base-in-register: exit status")
10229     # don't restore from ebp
10230     81 0/subop/add %esp 8/imm32
10231     # . epilogue
10232     5d/pop-to-ebp
10233     c3/return
10234 
10235 test-length-with-wrong-output-type:
10236     # . prologue
10237     55/push-ebp
10238     89/<- %ebp 4/r32/esp
10239     # setup
10240     (clear-stream _test-input-stream)
10241     (clear-stream $_test-input-buffered-file->buffer)
10242     (clear-stream _test-output-stream)
10243     (clear-stream $_test-output-buffered-file->buffer)
10244     (clear-stream _test-error-stream)
10245     (clear-stream $_test-error-buffered-file->buffer)
10246     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10247     68/push 0/imm32
10248     68/push 0/imm32
10249     89/<- %edx 4/r32/esp
10250     (tailor-exit-descriptor %edx 0x10)
10251     #
10252     (write _test-input-stream "fn foo {\n")
10253     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10254     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
10255     (write _test-input-stream "}\n")
10256     # convert
10257     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10258     # registers except esp clobbered at this point
10259     # restore ed
10260     89/<- %edx 4/r32/esp
10261     (flush _test-output-buffered-file)
10262     (flush _test-error-buffered-file)
10263 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10269     # check output
10270     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
10271     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-type: error message")
10272     # check that stop(1) was called
10273     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
10274     # don't restore from ebp
10275     81 0/subop/add %esp 8/imm32
10276     # . epilogue
10277     5d/pop-to-ebp
10278     c3/return
10279 
10280 test-length-with-wrong-output-compound-type:
10281     # . prologue
10282     55/push-ebp
10283     89/<- %ebp 4/r32/esp
10284     # setup
10285     (clear-stream _test-input-stream)
10286     (clear-stream $_test-input-buffered-file->buffer)
10287     (clear-stream _test-output-stream)
10288     (clear-stream $_test-output-buffered-file->buffer)
10289     (clear-stream _test-error-stream)
10290     (clear-stream $_test-error-buffered-file->buffer)
10291     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10292     68/push 0/imm32
10293     68/push 0/imm32
10294     89/<- %edx 4/r32/esp
10295     (tailor-exit-descriptor %edx 0x10)
10296     #
10297     (write _test-input-stream "fn foo {\n")
10298     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
10299     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
10300     (write _test-input-stream "}\n")
10301     # convert
10302     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10303     # registers except esp clobbered at this point
10304     # restore ed
10305     89/<- %edx 4/r32/esp
10306     (flush _test-output-buffered-file)
10307     (flush _test-error-buffered-file)
10308 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10314     # check output
10315     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
10316     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-compound-type: error message")
10317     # check that stop(1) was called
10318     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
10319     # don't restore from ebp
10320     81 0/subop/add %esp 8/imm32
10321     # . epilogue
10322     5d/pop-to-ebp
10323     c3/return
10324 
10325 test-length-with-no-inouts:
10326     # . prologue
10327     55/push-ebp
10328     89/<- %ebp 4/r32/esp
10329     # setup
10330     (clear-stream _test-input-stream)
10331     (clear-stream $_test-input-buffered-file->buffer)
10332     (clear-stream _test-output-stream)
10333     (clear-stream $_test-output-buffered-file->buffer)
10334     (clear-stream _test-error-stream)
10335     (clear-stream $_test-error-buffered-file->buffer)
10336     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10337     68/push 0/imm32
10338     68/push 0/imm32
10339     89/<- %edx 4/r32/esp
10340     (tailor-exit-descriptor %edx 0x10)
10341     #
10342     (write _test-input-stream "fn foo {\n")
10343     (write _test-input-stream "  var c/ecx: int <- length\n")
10344     (write _test-input-stream "}\n")
10345     # convert
10346     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10347     # registers except esp clobbered at this point
10348     # restore ed
10349     89/<- %edx 4/r32/esp
10350     (flush _test-output-buffered-file)
10351     (flush _test-error-buffered-file)
10352 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10358     # check output
10359     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
10360     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too few inouts (1 required)"  "F - test-length-with-no-inouts: error message")
10361     # check that stop(1) was called
10362     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
10363     # don't restore from ebp
10364     81 0/subop/add %esp 8/imm32
10365     # . epilogue
10366     5d/pop-to-ebp
10367     c3/return
10368 
10369 test-length-with-too-many-inouts:
10370     # . prologue
10371     55/push-ebp
10372     89/<- %ebp 4/r32/esp
10373     # setup
10374     (clear-stream _test-input-stream)
10375     (clear-stream $_test-input-buffered-file->buffer)
10376     (clear-stream _test-output-stream)
10377     (clear-stream $_test-output-buffered-file->buffer)
10378     (clear-stream _test-error-stream)
10379     (clear-stream $_test-error-buffered-file->buffer)
10380     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10381     68/push 0/imm32
10382     68/push 0/imm32
10383     89/<- %edx 4/r32/esp
10384     (tailor-exit-descriptor %edx 0x10)
10385     #
10386     (write _test-input-stream "fn foo {\n")
10387     (write _test-input-stream "  var a: (array int 3)\n")
10388     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
10389     (write _test-input-stream "}\n")
10390     # convert
10391     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10392     # registers except esp clobbered at this point
10393     # restore ed
10394     89/<- %edx 4/r32/esp
10395     (flush _test-output-buffered-file)
10396     (flush _test-error-buffered-file)
10397 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10403     # check output
10404     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
10405     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many inouts (1 required)"  "F - test-length-with-too-many-inouts: error message")
10406     # check that stop(1) was called
10407     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
10408     # don't restore from ebp
10409     81 0/subop/add %esp 8/imm32
10410     # . epilogue
10411     5d/pop-to-ebp
10412     c3/return
10413 
10414 test-length-with-no-output:
10415     # . prologue
10416     55/push-ebp
10417     89/<- %ebp 4/r32/esp
10418     # setup
10419     (clear-stream _test-input-stream)
10420     (clear-stream $_test-input-buffered-file->buffer)
10421     (clear-stream _test-output-stream)
10422     (clear-stream $_test-output-buffered-file->buffer)
10423     (clear-stream _test-error-stream)
10424     (clear-stream $_test-error-buffered-file->buffer)
10425     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10426     68/push 0/imm32
10427     68/push 0/imm32
10428     89/<- %edx 4/r32/esp
10429     (tailor-exit-descriptor %edx 0x10)
10430     #
10431     (write _test-input-stream "fn foo {\n")
10432     (write _test-input-stream "  var a: (array int 3)\n")
10433     (write _test-input-stream "  length a\n")
10434     (write _test-input-stream "}\n")
10435     # convert
10436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10437     # registers except esp clobbered at this point
10438     # restore ed
10439     89/<- %edx 4/r32/esp
10440     (flush _test-output-buffered-file)
10441     (flush _test-error-buffered-file)
10442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10448     # check output
10449     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
10450     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
10451     # check that stop(1) was called
10452     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
10453     # don't restore from ebp
10454     81 0/subop/add %esp 8/imm32
10455     # . epilogue
10456     5d/pop-to-ebp
10457     c3/return
10458 
10459 test-length-with-too-many-outputs:
10460     # . prologue
10461     55/push-ebp
10462     89/<- %ebp 4/r32/esp
10463     # setup
10464     (clear-stream _test-input-stream)
10465     (clear-stream $_test-input-buffered-file->buffer)
10466     (clear-stream _test-output-stream)
10467     (clear-stream $_test-output-buffered-file->buffer)
10468     (clear-stream _test-error-stream)
10469     (clear-stream $_test-error-buffered-file->buffer)
10470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10471     68/push 0/imm32
10472     68/push 0/imm32
10473     89/<- %edx 4/r32/esp
10474     (tailor-exit-descriptor %edx 0x10)
10475     #
10476     (write _test-input-stream "fn foo {\n")
10477     (write _test-input-stream "  var a: (array int 3)\n")
10478     (write _test-input-stream "  var b/eax: int <- copy 0\n")
10479     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
10480     (write _test-input-stream "  b, c <- length a\n")
10481     (write _test-input-stream "}\n")
10482     # convert
10483     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10484     # registers except esp clobbered at this point
10485     # restore ed
10486     89/<- %edx 4/r32/esp
10487     (flush _test-output-buffered-file)
10488     (flush _test-error-buffered-file)
10489 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10495     # check output
10496     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
10497     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many outputs (1 required)"  "F - test-length-with-too-many-outputs: error message")
10498     # check that stop(1) was called
10499     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
10500     # don't restore from ebp
10501     81 0/subop/add %esp 8/imm32
10502     # . epilogue
10503     5d/pop-to-ebp
10504     c3/return
10505 
10506 test-convert-function-with-return-register-and-local:
10507     # . prologue
10508     55/push-ebp
10509     89/<- %ebp 4/r32/esp
10510     # setup
10511     (clear-stream _test-input-stream)
10512     (clear-stream $_test-input-buffered-file->buffer)
10513     (clear-stream _test-output-stream)
10514     (clear-stream $_test-output-buffered-file->buffer)
10515     #
10516     (write _test-input-stream "fn foo -> _/eax: int {\n")
10517     (write _test-input-stream "  var y/eax: int <- copy 3\n")
10518     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
10519     (write _test-input-stream "  return y\n")
10520     (write _test-input-stream "}\n")
10521     # convert
10522     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10523     (flush _test-output-buffered-file)
10524 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10530     # check output
10531     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
10532     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
10533     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
10534     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
10535     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
10536     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
10537     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
10538     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
10539     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
10540     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
10541     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
10542     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
10543     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local/12")
10544     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
10545     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
10546     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
10547     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
10548     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
10549     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
10550     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
10551     # . epilogue
10552     89/<- %esp 5/r32/ebp
10553     5d/pop-to-ebp
10554     c3/return
10555 
10556 test-convert-function-with-return-register-and-local-2:
10557     # . prologue
10558     55/push-ebp
10559     89/<- %ebp 4/r32/esp
10560     # setup
10561     (clear-stream _test-input-stream)
10562     (clear-stream $_test-input-buffered-file->buffer)
10563     (clear-stream _test-output-stream)
10564     (clear-stream $_test-output-buffered-file->buffer)
10565     #
10566     (write _test-input-stream "fn foo -> _/eax: int {\n")
10567     (write _test-input-stream "  var y/eax: int <- copy 3\n")
10568     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
10569     (write _test-input-stream "  return z\n")
10570     (write _test-input-stream "}\n")
10571     # convert
10572     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10573     (flush _test-output-buffered-file)
10574 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10580     # check output
10581     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
10582     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
10583     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
10584     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
10585     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
10586     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
10587     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
10588     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local-2/7")
10589     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
10590     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/9")
10591     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
10592     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
10593     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/12")
10594     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local-2/13")
10595     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
10596     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
10597     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
10598     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
10599     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
10600     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
10601     # . epilogue
10602     89/<- %esp 5/r32/ebp
10603     5d/pop-to-ebp
10604     c3/return
10605 
10606 test-convert-function-with-return-float-register-and-local:
10607     # . prologue
10608     55/push-ebp
10609     89/<- %ebp 4/r32/esp
10610     # setup
10611     (clear-stream _test-input-stream)
10612     (clear-stream $_test-input-buffered-file->buffer)
10613     (clear-stream _test-output-stream)
10614     (clear-stream $_test-output-buffered-file->buffer)
10615     #
10616     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
10617     (write _test-input-stream "  var y/eax: int <- copy 3\n")
10618     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
10619     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
10620     (write _test-input-stream "  return g\n")
10621     (write _test-input-stream "}\n")
10622     # convert
10623     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10624     (flush _test-output-buffered-file)
10625 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10631     # check output
10632     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
10633     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
10634     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
10635     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
10636     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
10637     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
10638     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-float-register-and-local/6")  # var y
10639     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-float-register-and-local/7")
10640     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/8")  # var g
10641     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 0/x32"  "F - test-convert-function-with-return-float-register-and-local/9")
10642     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000000/x32"  "F - test-convert-function-with-return-float-register-and-local/10")
10643     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/11")  # var h
10644     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-function-with-return-float-register-and-local/12")
10645     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/13")
10646     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> %xmm0 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/14")  # return g
10647     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
10648     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
10649     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
10650     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"         "F - test-convert-function-with-return-float-register-and-local/18")  # reclaim y
10651     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-float-register-and-local/19")
10652     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
10653     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
10654     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
10655     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
10656     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
10657     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
10658     # . epilogue
10659     89/<- %esp 5/r32/ebp
10660     5d/pop-to-ebp
10661     c3/return
10662 
10663 test-convert-function-with-return-and-local-vars:
10664     # . prologue
10665     55/push-ebp
10666     89/<- %ebp 4/r32/esp
10667     # setup
10668     (clear-stream _test-input-stream)
10669     (clear-stream $_test-input-buffered-file->buffer)
10670     (clear-stream _test-output-stream)
10671     (clear-stream $_test-output-buffered-file->buffer)
10672     #
10673     (write _test-input-stream "fn foo -> _/eax: int {\n")
10674     (write _test-input-stream "  {\n")
10675     (write _test-input-stream "    var x: int\n")
10676     (write _test-input-stream "    {\n")
10677     (write _test-input-stream "      var y: int\n")
10678     (write _test-input-stream "      return y\n")
10679     (write _test-input-stream "      increment x\n")
10680     (write _test-input-stream "    }\n")
10681     (write _test-input-stream "  }\n")
10682     (write _test-input-stream "  return 0\n")
10683     (write _test-input-stream "}\n")
10684     # convert
10685     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10686     (flush _test-output-buffered-file)
10687 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10693     # check output
10694     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
10695     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
10696     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
10697     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
10698     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
10699     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
10700     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
10701     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
10702     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
10703     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
10704     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
10705     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
10706     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
10707     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/13")
10708     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/14")
10709     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
10710     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
10711     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
10712     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/18")
10713     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
10714     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
10715     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-and-local-vars/21")
10716     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
10717     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
10718     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
10719     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
10720     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
10721     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
10722     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
10723     # . epilogue
10724     89/<- %esp 5/r32/ebp
10725     5d/pop-to-ebp
10726     c3/return
10727 
10728 #######################################################
10729 # Parsing
10730 #######################################################
10731 
10732 == data
10733 
10734 # Global state added to each var record when parsing a function
10735 Next-block-index:  # (addr int)
10736     1/imm32
10737 
10738 Curr-block-depth:  # (addr int)
10739     1/imm32
10740 
10741 == code
10742 
10743 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
10744     # pseudocode
10745     #   var curr-function: (addr handle function) = Program->functions
10746     #   var curr-signature: (addr handle function) = Program->signatures
10747     #   var curr-type: (addr handle typeinfo) = Program->types
10748     #   var line: (stream byte 512)
10749     #   var word-slice: slice
10750     #   while true                                  # line loop
10751     #     clear-stream(line)
10752     #     read-line-buffered(in, line)
10753     #     if (line->write == 0) break               # end of file
10754     #     word-slice = next-mu-token(line)
10755     #     if slice-empty?(word-slice)               # end of line
10756     #       continue
10757     #     else if slice-starts-with?(word-slice, "#")  # comment
10758     #       continue                                # end of line
10759     #     else if slice-equal?(word-slice, "fn")
10760     #       var new-function: (handle function) = allocate(function)
10761     #       var vars: (stack live-var 256)
10762     #       populate-mu-function-header(line, new-function, vars)
10763     #       populate-mu-function-body(in, new-function, vars)
10764     #       assert(vars->top == 0)
10765     #       *curr-function = new-function
10766     #       curr-function = &new-function->next
10767     #     else if slice-equal?(word-slice, "sig")
10768     #       var new-function: (handle function) = allocate(function)
10769     #       populate-mu-function-signature(line, new-function)
10770     #       *curr-signature = new-function
10771     #       curr-signature = &new-function->next
10772     #     else if slice-equal?(word-slice, "type")
10773     #       word-slice = next-mu-token(line)
10774     #       type-id = pos-or-insert-slice(Type-id, word-slice)
10775     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
10776     #       assert(next-word(line) == "{")
10777     #       populate-mu-type(in, new-type)
10778     #     else
10779     #       abort()
10780     #
10781     # . prologue
10782     55/push-ebp
10783     89/<- %ebp 4/r32/esp
10784     # var curr-signature: (addr handle function) at *(ebp-4)
10785     68/push _Program-signatures/imm32
10786     # . save registers
10787     50/push-eax
10788     51/push-ecx
10789     52/push-edx
10790     53/push-ebx
10791     56/push-esi
10792     57/push-edi
10793     # var line/ecx: (stream byte 512)
10794     81 5/subop/subtract %esp 0x200/imm32
10795     68/push 0x200/imm32/size
10796     68/push 0/imm32/read
10797     68/push 0/imm32/write
10798     89/<- %ecx 4/r32/esp
10799     # var word-slice/edx: slice
10800     68/push 0/imm32/end
10801     68/push 0/imm32/start
10802     89/<- %edx 4/r32/esp
10803     # var curr-function/edi: (addr handle function)
10804     bf/copy-to-edi _Program-functions/imm32
10805     # var vars/ebx: (stack live-var 256)
10806     81 5/subop/subtract %esp 0xc00/imm32
10807     68/push 0xc00/imm32/size
10808     68/push 0/imm32/top
10809     89/<- %ebx 4/r32/esp
10810     {
10811 $parse-mu:line-loop:
10812       (clear-stream %ecx)
10813       (read-line-buffered *(ebp+8) %ecx)
10814       # if (line->write == 0) break
10815       81 7/subop/compare *ecx 0/imm32
10816       0f 84/jump-if-= break/disp32
10817 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
10823       (next-mu-token %ecx %edx)
10824       # if slice-empty?(word-slice) continue
10825       (slice-empty? %edx)  # => eax
10826       3d/compare-eax-and 0/imm32/false
10827       0f 85/jump-if-!= loop/disp32
10828       # if (*word-slice->start == "#") continue
10829       # . eax = *word-slice->start
10830       8b/-> *edx 0/r32/eax
10831       8a/copy-byte *eax 0/r32/AL
10832       81 4/subop/and %eax 0xff/imm32
10833       # . if (eax == '#') continue
10834       3d/compare-eax-and 0x23/imm32/hash
10835       0f 84/jump-if-= loop/disp32
10836       # if (slice-equal?(word-slice, "fn")) parse a function
10837       {
10838 $parse-mu:fn:
10839         (slice-equal? %edx "fn")  # => eax
10840         3d/compare-eax-and 0/imm32/false
10841         0f 84/jump-if-= break/disp32
10842         # var new-function/esi: (handle function)
10843         68/push 0/imm32
10844         68/push 0/imm32
10845         89/<- %esi 4/r32/esp
10846         # populate-mu-function(line, in, vars, new-function)
10847         (allocate Heap *Function-size %esi)
10848         # var new-function-addr/eax: (addr function)
10849         (lookup *esi *(esi+4))  # => eax
10850         # initialize vars
10851         (clear-stack %ebx)
10852         #
10853         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
10854         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
10855         # *curr-function = new-function
10856         8b/-> *esi 0/r32/eax
10857         89/<- *edi 0/r32/eax
10858         8b/-> *(esi+4) 0/r32/eax
10859         89/<- *(edi+4) 0/r32/eax
10860         # curr-function = &new-function->next
10861         # . var tmp/eax: (addr function) = lookup(new-function)
10862         (lookup *esi *(esi+4))  # => eax
10863         # . curr-function = &tmp->next
10864         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
10865         # reclaim new-function
10866         81 0/subop/add %esp 8/imm32
10867         #
10868         e9/jump $parse-mu:line-loop/disp32
10869       }
10870       # if (slice-equal?(word-slice, "sig")) parse a function signature
10871       # Function signatures are for providing types to SubX functions.
10872       {
10873 $parse-mu:sig:
10874         (slice-equal? %edx "sig")  # => eax
10875         3d/compare-eax-and 0/imm32/false
10876         0f 84/jump-if-= break/disp32
10877         # edi = curr-function
10878         57/push-edi
10879         8b/-> *(ebp-4) 7/r32/edi
10880         # var new-function/esi: (handle function)
10881         68/push 0/imm32
10882         68/push 0/imm32
10883         89/<- %esi 4/r32/esp
10884         # populate-mu-function(line, in, vars, new-function)
10885         (allocate Heap *Function-size %esi)
10886         # var new-function-addr/eax: (addr function)
10887         (lookup *esi *(esi+4))  # => eax
10888         #
10889         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
10890         # *curr-signature = new-function
10891         8b/-> *esi 0/r32/eax
10892         89/<- *edi 0/r32/eax
10893         8b/-> *(esi+4) 0/r32/eax
10894         89/<- *(edi+4) 0/r32/eax
10895         # curr-signature = &new-function->next
10896         # . var tmp/eax: (addr function) = lookup(new-function)
10897         (lookup *esi *(esi+4))  # => eax
10898         # . curr-function = &tmp->next
10899         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
10900         # reclaim new-function
10901         81 0/subop/add %esp 8/imm32
10902         # save curr-function
10903         89/<- *(ebp-4) 7/r32/edi
10904         # restore edi
10905         5f/pop-to-edi
10906         #
10907         e9/jump $parse-mu:line-loop/disp32
10908       }
10909       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
10910       {
10911 $parse-mu:type:
10912         (slice-equal? %edx "type")  # => eax
10913         3d/compare-eax-and 0/imm32
10914         0f 84/jump-if-= break/disp32
10915         (next-mu-token %ecx %edx)
10916         # var type-id/eax: int
10917         (pos-or-insert-slice Type-id %edx)  # => eax
10918         # spill
10919         51/push-ecx
10920         # var new-type/ecx: (handle typeinfo)
10921         68/push 0/imm32
10922         68/push 0/imm32
10923         89/<- %ecx 4/r32/esp
10924         (find-or-create-typeinfo %eax %ecx)
10925         #
10926         (lookup *ecx *(ecx+4))  # => eax
10927         # TODO: ensure that 'line' has nothing else but '{'
10928 #? (dump-typeinfos "=== aaa\n")
10929         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
10930 #? (dump-typeinfos "=== zzz\n")
10931         # reclaim new-type
10932         81 0/subop/add %esp 8/imm32
10933         # restore
10934         59/pop-to-ecx
10935         e9/jump $parse-mu:line-loop/disp32
10936       }
10937       # otherwise abort
10938       e9/jump $parse-mu:error1/disp32
10939     } # end line loop
10940 $parse-mu:end:
10941     # . reclaim locals
10942     81 0/subop/add %esp 0x20c/imm32  # line
10943     81 0/subop/add %esp 0xc08/imm32  # vars
10944     81 0/subop/add %esp 8/imm32
10945     # . restore registers
10946     5f/pop-to-edi
10947     5e/pop-to-esi
10948     5b/pop-to-ebx
10949     5a/pop-to-edx
10950     59/pop-to-ecx
10951     58/pop-to-eax
10952     # . reclaim local
10953     81 0/subop/add %esp 4/imm32
10954     # . epilogue
10955     89/<- %esp 5/r32/ebp
10956     5d/pop-to-ebp
10957     c3/return
10958 
10959 $parse-mu:error1:
10960     # error("unexpected top-level command: " word-slice "\n")
10961     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
10962     (write-slice-buffered *(ebp+0xc) %edx)
10963     (write-buffered *(ebp+0xc) "\n")
10964     (flush *(ebp+0xc))
10965     (stop *(ebp+0x10) 1)
10966     # never gets here
10967 
10968 $parse-mu:error2:
10969     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
10970     (write-int32-hex-buffered *(ebp+0xc) *ebx)
10971     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
10972     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
10973     (write-buffered *(ebp+0xc) "'\n")
10974     (flush *(ebp+0xc))
10975     (stop *(ebp+0x10) 1)
10976     # never gets here
10977 
10978 # scenarios considered:
10979 # ✗ fn foo  # no block
10980 # ✓ fn foo {
10981 # ✗ fn foo { {
10982 # ✗ fn foo { }
10983 # ✗ fn foo { } {
10984 # ✗ fn foo x {
10985 # ✗ fn foo x: {
10986 # ✓ fn foo x: int {
10987 # ✓ fn foo x: int {
10988 # ✓ fn foo x: int -> _/eax: int {
10989 # TODO:
10990 #   disallow outputs of type `(... addr ...)`
10991 #   disallow inputs of type `(... addr ... addr ...)`
10992 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)
10993     # pseudocode:
10994     #   var word-slice: slice
10995     #   next-mu-token(first-line, word-slice)
10996     #   if slice-empty?(word-slice) abort
10997     #   assert(word-slice not in '{' '}' '->')
10998     #   out->name = slice-to-string(word-slice)
10999     #   ## inouts
11000     #   while true
11001     #     word-slice = next-mu-token(first-line)
11002     #     if slice-empty?(word-slice) abort
11003     #     if (word-slice == '{') goto done
11004     #     if (word-slice == '->') break
11005     #     assert(word-slice != '}')
11006     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
11007     #     assert(v->register == null)
11008     #     # v->block-depth is implicitly 0
11009     #     out->inouts = append(v, out->inouts)
11010     #     push(vars, {v, false})
11011     #   ## outputs
11012     #   while true
11013     #     word-slice = next-mu-token(first-line)
11014     #     if slice-empty?(word-slice) abort
11015     #     if (word-slice == '{') break
11016     #     assert(word-slice not in '}' '->')
11017     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
11018     #     assert(v->register != null)
11019     #     assert(v->name == "_")
11020     #     out->outputs = append(v, out->outputs)
11021     #   done:
11022     #
11023     # . prologue
11024     55/push-ebp
11025     89/<- %ebp 4/r32/esp
11026     # . save registers
11027     50/push-eax
11028     51/push-ecx
11029     52/push-edx
11030     53/push-ebx
11031     57/push-edi
11032     # edi = out
11033     8b/-> *(ebp+0xc) 7/r32/edi
11034     # var word-slice/ecx: slice
11035     68/push 0/imm32/end
11036     68/push 0/imm32/start
11037     89/<- %ecx 4/r32/esp
11038     # var v/ebx: (handle var)
11039     68/push 0/imm32
11040     68/push 0/imm32
11041     89/<- %ebx 4/r32/esp
11042     # read function name
11043     (next-mu-token *(ebp+8) %ecx)
11044     # error checking
11045     # if slice-empty?(word-slice) abort
11046     (slice-empty? %ecx)  # => eax
11047     3d/compare-eax-and 0/imm32/false
11048     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11049     # if (word-slice == '{') abort
11050     (slice-equal? %ecx "{")   # => eax
11051     3d/compare-eax-and 0/imm32/false
11052     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11053     # if (word-slice == '->') abort
11054     (slice-equal? %ecx "->")   # => eax
11055     3d/compare-eax-and 0/imm32/false
11056     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11057     # if (word-slice == '}') abort
11058     (slice-equal? %ecx "}")   # => eax
11059     3d/compare-eax-and 0/imm32/false
11060     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11061     # save function name
11062     (slice-to-string Heap %ecx %edi)  # Function-name
11063     # save function inouts
11064     {
11065 $populate-mu-function-header:check-for-inout:
11066       (next-mu-token *(ebp+8) %ecx)
11067       # if slice-empty?(word-slice) abort
11068       (slice-empty? %ecx)  # => eax
11069       3d/compare-eax-and 0/imm32/false
11070       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11071       # if (word-slice == '{') goto done
11072       (slice-equal? %ecx "{")   # => eax
11073       3d/compare-eax-and 0/imm32/false
11074       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
11075       # if (word-slice == '->') break
11076       (slice-equal? %ecx "->")   # => eax
11077       3d/compare-eax-and 0/imm32/false
11078       0f 85/jump-if-!= break/disp32
11079       # if (word-slice == '}') abort
11080       (slice-equal? %ecx "}")   # => eax
11081       3d/compare-eax-and 0/imm32/false
11082       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11083       # v = parse-var-with-type(word-slice, first-line)
11084       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
11085       # assert(v->register == null)
11086       # . eax: (addr var) = lookup(v)
11087       (lookup *ebx *(ebx+4))  # => eax
11088       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
11089       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
11090       # v->block-depth is implicitly 0
11091       #
11092       # out->inouts = append(v, out->inouts)
11093       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
11094       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
11095       # push(vars, {v, false})
11096       (push *(ebp+0x10) *ebx)
11097       (push *(ebp+0x10) *(ebx+4))
11098       (push *(ebp+0x10) 0)  # false
11099       #
11100       e9/jump loop/disp32
11101     }
11102     # save function outputs
11103     {
11104 $populate-mu-function-header:check-for-out:
11105       (next-mu-token *(ebp+8) %ecx)
11106       # if slice-empty?(word-slice) abort
11107       (slice-empty? %ecx)  # => eax
11108       3d/compare-eax-and 0/imm32/false
11109       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11110       # if (word-slice == '{') break
11111       (slice-equal? %ecx "{")   # => eax
11112       3d/compare-eax-and 0/imm32/false
11113       0f 85/jump-if-!= break/disp32
11114       # if (word-slice == '->') abort
11115       (slice-equal? %ecx "->")   # => eax
11116       3d/compare-eax-and 0/imm32/false
11117       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11118       # if (word-slice == '}') abort
11119       (slice-equal? %ecx "}")   # => eax
11120       3d/compare-eax-and 0/imm32/false
11121       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
11122       # v = parse-var-with-type(word-slice, first-line)
11123       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
11124       # assert(var->register != null)
11125       # . eax: (addr var) = lookup(v)
11126       (lookup *ebx *(ebx+4))  # => eax
11127       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
11128       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
11129       # assert(var->name == "_")
11130       (lookup *eax *(eax+4))  # Var-name Var-name => eax
11131       (string-equal? %eax "_")  # => eax
11132       3d/compare-eax-and 0/imm32/false
11133       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
11134       # out->outputs = append(v, out->outputs)
11135       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
11136       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
11137       #
11138       e9/jump loop/disp32
11139     }
11140 $populate-mu-function-header:done:
11141     (check-no-tokens-left *(ebp+8))
11142 $populate-mu-function-header:end:
11143     # . reclaim locals
11144     81 0/subop/add %esp 0x10/imm32
11145     # . restore registers
11146     5f/pop-to-edi
11147     5b/pop-to-ebx
11148     5a/pop-to-edx
11149     59/pop-to-ecx
11150     58/pop-to-eax
11151     # . epilogue
11152     89/<- %esp 5/r32/ebp
11153     5d/pop-to-ebp
11154     c3/return
11155 
11156 $populate-mu-function-header:error1:
11157     # error("function header not in form 'fn <name> {'")
11158     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
11159     (flush *(ebp+0x14))
11160     (rewind-stream *(ebp+8))
11161     (write-stream-data *(ebp+0x14) *(ebp+8))
11162     (write-buffered *(ebp+0x14) "'\n")
11163     (flush *(ebp+0x14))
11164     (stop *(ebp+0x18) 1)
11165     # never gets here
11166 
11167 $populate-mu-function-header:error2:
11168     # error("fn " fn ": function inout '" var "' cannot be in a register")
11169     (write-buffered *(ebp+0x14) "fn ")
11170     50/push-eax
11171     (lookup *edi *(edi+4))  # Function-name Function-name => eax
11172     (write-buffered *(ebp+0x14) %eax)
11173     58/pop-to-eax
11174     (write-buffered *(ebp+0x14) ": function inout '")
11175     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11176     (write-buffered *(ebp+0x14) %eax)
11177     (write-buffered *(ebp+0x14) "' cannot be in a register")
11178     (flush *(ebp+0x14))
11179     (stop *(ebp+0x18) 1)
11180     # never gets here
11181 
11182 $populate-mu-function-header:error3:
11183     # error("fn " fn ": function output '" var "' must be in a register")
11184     (write-buffered *(ebp+0x14) "fn ")
11185     50/push-eax
11186     (lookup *edi *(edi+4))  # Function-name Function-name => eax
11187     (write-buffered *(ebp+0x14) %eax)
11188     58/pop-to-eax
11189     (write-buffered *(ebp+0x14) ": function output '")
11190     (lookup *ebx *(ebx+4))  # => eax
11191     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11192     (write-buffered *(ebp+0x14) %eax)
11193     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
11194     (rewind-stream *(ebp+8))
11195     (write-stream-data *(ebp+0x14) *(ebp+8))
11196     (write-buffered *(ebp+0x14) "'\n")
11197     (flush *(ebp+0x14))
11198     (stop *(ebp+0x18) 1)
11199     # never gets here
11200 
11201 $populate-mu-function-header:error4:
11202     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
11203     (write-buffered *(ebp+0x14) "fn ")
11204     50/push-eax
11205     (lookup *edi *(edi+4))  # Function-name Function-name => eax
11206     (write-buffered *(ebp+0x14) %eax)
11207     58/pop-to-eax
11208     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
11209     (lookup *ebx *(ebx+4))  # => eax
11210     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11211     (write-buffered *(ebp+0x14) %eax)
11212     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
11213     (flush *(ebp+0x14))
11214     (stop *(ebp+0x18) 1)
11215     # never gets here
11216 
11217 # scenarios considered:
11218 # ✓ fn foo
11219 # ✗ fn foo {
11220 # ✓ fn foo x
11221 # ✓ fn foo x: int
11222 # ✓ fn foo x: int -> _/eax: int
11223 # TODO:
11224 #   disallow outputs of type `(... addr ...)`
11225 #   disallow inputs of type `(... addr ... addr ...)`
11226 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
11227     # pseudocode:
11228     #   var word-slice: slice
11229     #   next-mu-token(first-line, word-slice)
11230     #   assert(word-slice not in '{' '}' '->')
11231     #   out->name = slice-to-string(word-slice)
11232     #   ## inouts
11233     #   while true
11234     #     word-slice = next-mu-token(first-line)
11235     #     if slice-empty?(word-slice) break
11236     #     if (word-slice == '->') break
11237     #     assert(word-slice not in '{' '}')
11238     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
11239     #     assert(v->register == null)
11240     #     # v->block-depth is implicitly 0
11241     #     out->inouts = append(v, out->inouts)
11242     #   ## outputs
11243     #   while true
11244     #     word-slice = next-mu-token(first-line)
11245     #     if slice-empty?(word-slice) break
11246     #     assert(word-slice not in '{' '}' '->')
11247     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
11248     #     assert(v->register != null)
11249     #     out->outputs = append(v, out->outputs)
11250     #
11251     # . prologue
11252     55/push-ebp
11253     89/<- %ebp 4/r32/esp
11254     # . save registers
11255     50/push-eax
11256     51/push-ecx
11257     52/push-edx
11258     53/push-ebx
11259     57/push-edi
11260     # edi = out
11261     8b/-> *(ebp+0xc) 7/r32/edi
11262     # var word-slice/ecx: slice
11263     68/push 0/imm32/end
11264     68/push 0/imm32/start
11265     89/<- %ecx 4/r32/esp
11266     # var v/ebx: (handle var)
11267     68/push 0/imm32
11268     68/push 0/imm32
11269     89/<- %ebx 4/r32/esp
11270     # read function name
11271     (next-mu-token *(ebp+8) %ecx)
11272     # error checking
11273     # if (word-slice == '{') abort
11274     (slice-equal? %ecx "{")   # => eax
11275     3d/compare-eax-and 0/imm32/false
11276     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11277     # if (word-slice == '->') abort
11278     (slice-equal? %ecx "->")   # => eax
11279     3d/compare-eax-and 0/imm32/false
11280     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11281     # if (word-slice == '}') abort
11282     (slice-equal? %ecx "}")   # => eax
11283     3d/compare-eax-and 0/imm32/false
11284     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11285     # save function name
11286     (slice-to-string Heap %ecx %edi)  # Function-name
11287     # save function inouts
11288     {
11289 $populate-mu-function-signature:check-for-inout:
11290       (next-mu-token *(ebp+8) %ecx)
11291       (slice-empty? %ecx)  # => eax
11292       3d/compare-eax-and 0/imm32/false
11293       0f 85/jump-if-!= break/disp32
11294       # if (word-slice == '->') break
11295       (slice-equal? %ecx "->")   # => eax
11296       3d/compare-eax-and 0/imm32/false
11297       0f 85/jump-if-!= break/disp32
11298       # if (word-slice == '{') abort
11299       (slice-equal? %ecx "{")   # => eax
11300       3d/compare-eax-and 0/imm32/false
11301       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11302       # if (word-slice == '}') abort
11303       (slice-equal? %ecx "}")   # => eax
11304       3d/compare-eax-and 0/imm32/false
11305       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11306       # v = parse-var-with-type(word-slice, first-line)
11307       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
11308       # assert(v->register == null)
11309       # . eax: (addr var) = lookup(v)
11310       (lookup *ebx *(ebx+4))  # => eax
11311       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
11312       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
11313       # v->block-depth is implicitly 0
11314       #
11315       # out->inouts = append(v, out->inouts)
11316       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
11317       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
11318       #
11319       e9/jump loop/disp32
11320     }
11321     # save function outputs
11322     {
11323 $populate-mu-function-signature:check-for-out:
11324       (next-mu-token *(ebp+8) %ecx)
11325       (slice-empty? %ecx)  # => eax
11326       3d/compare-eax-and 0/imm32/false
11327       0f 85/jump-if-!= break/disp32
11328       # if (word-slice == '{') abort
11329       (slice-equal? %ecx "{")   # => eax
11330       3d/compare-eax-and 0/imm32/false
11331       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11332       # if (word-slice == '->') abort
11333       (slice-equal? %ecx "->")   # => eax
11334       3d/compare-eax-and 0/imm32/false
11335       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11336       # if (word-slice == '}') abort
11337       (slice-equal? %ecx "}")   # => eax
11338       3d/compare-eax-and 0/imm32/false
11339       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
11340       # v = parse-var-with-type(word-slice, first-line)
11341       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
11342       # assert(var->register != null)
11343       # . eax: (addr var) = lookup(v)
11344       (lookup *ebx *(ebx+4))  # => eax
11345       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
11346       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
11347       # out->outputs = append(v, out->outputs)
11348       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
11349       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
11350       #
11351       e9/jump loop/disp32
11352     }
11353 $populate-mu-function-signature:done:
11354     (check-no-tokens-left *(ebp+8))
11355 $populate-mu-function-signature:end:
11356     # . reclaim locals
11357     81 0/subop/add %esp 0x10/imm32
11358     # . restore registers
11359     5f/pop-to-edi
11360     5b/pop-to-ebx
11361     5a/pop-to-edx
11362     59/pop-to-ecx
11363     58/pop-to-eax
11364     # . epilogue
11365     89/<- %esp 5/r32/ebp
11366     5d/pop-to-ebp
11367     c3/return
11368 
11369 $populate-mu-function-signature:error1:
11370     # error("function signature not in form 'fn <name> {'")
11371     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
11372     (flush *(ebp+0x10))
11373     (rewind-stream *(ebp+8))
11374     (write-stream-data *(ebp+0x10) *(ebp+8))
11375     (write-buffered *(ebp+0x10) "'\n")
11376     (flush *(ebp+0x10))
11377     (stop *(ebp+0x14) 1)
11378     # never gets here
11379 
11380 $populate-mu-function-signature:error2:
11381     # error("fn " fn ": function inout '" var "' cannot be in a register")
11382     (write-buffered *(ebp+0x10) "fn ")
11383     50/push-eax
11384     (lookup *edi *(edi+4))  # Function-name Function-name => eax
11385     (write-buffered *(ebp+0x10) %eax)
11386     58/pop-to-eax
11387     (write-buffered *(ebp+0x10) ": function inout '")
11388     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11389     (write-buffered *(ebp+0x10) %eax)
11390     (write-buffered *(ebp+0x10) "' cannot be in a register")
11391     (flush *(ebp+0x10))
11392     (stop *(ebp+0x14) 1)
11393     # never gets here
11394 
11395 $populate-mu-function-signature:error3:
11396     # error("fn " fn ": function output '" var "' must be in a register")
11397     (write-buffered *(ebp+0x10) "fn ")
11398     50/push-eax
11399     (lookup *edi *(edi+4))  # Function-name Function-name => eax
11400     (write-buffered *(ebp+0x10) %eax)
11401     58/pop-to-eax
11402     (write-buffered *(ebp+0x10) ": function output '")
11403     (lookup *ebx *(ebx+4))  # => eax
11404     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11405     (write-buffered *(ebp+0x10) %eax)
11406     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
11407     (rewind-stream *(ebp+8))
11408     (write-stream-data *(ebp+0x10) *(ebp+8))
11409     (write-buffered *(ebp+0x10) "'\n")
11410     (flush *(ebp+0x10))
11411     (stop *(ebp+0x14) 1)
11412     # never gets here
11413 
11414 test-function-header-with-arg:
11415     # . prologue
11416     55/push-ebp
11417     89/<- %ebp 4/r32/esp
11418     # setup
11419     8b/-> *Primitive-type-ids 0/r32/eax
11420     89/<- *Type-id 0/r32/eax  # stream-write
11421     (clear-stream _test-input-stream)
11422     (write _test-input-stream "foo n: int {\n")
11423     # var result/ecx: function
11424     2b/subtract *Function-size 4/r32/esp
11425     89/<- %ecx 4/r32/esp
11426     (zero-out %ecx *Function-size)
11427     # var vars/ebx: (stack live-var 16)
11428     81 5/subop/subtract %esp 0xc0/imm32
11429     68/push 0xc0/imm32/size
11430     68/push 0/imm32/top
11431     89/<- %ebx 4/r32/esp
11432     # convert
11433     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
11434     # check result->name
11435     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
11436     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
11437     # var v/edx: (addr var) = result->inouts->value
11438     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
11439     (lookup *eax *(eax+4))  # List-value List-value => eax
11440     89/<- %edx 0/r32/eax
11441     # check v->name
11442     (lookup *edx *(edx+4))  # Var-name Var-name => eax
11443     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
11444     # check v->type
11445     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
11446     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
11447     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
11448     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
11449     # . epilogue
11450     89/<- %esp 5/r32/ebp
11451     5d/pop-to-ebp
11452     c3/return
11453 
11454 test-function-header-with-multiple-args:
11455     # . prologue
11456     55/push-ebp
11457     89/<- %ebp 4/r32/esp
11458     # setup
11459     8b/-> *Primitive-type-ids 0/r32/eax
11460     89/<- *Type-id 0/r32/eax  # stream-write
11461     (clear-stream _test-input-stream)
11462     (write _test-input-stream "foo a: int, b: int c: int {\n")
11463     # result/ecx: function
11464     2b/subtract *Function-size 4/r32/esp
11465     89/<- %ecx 4/r32/esp
11466     (zero-out %ecx *Function-size)
11467     # var vars/ebx: (stack live-var 16)
11468     81 5/subop/subtract %esp 0xc0/imm32
11469     68/push 0xc0/imm32/size
11470     68/push 0/imm32/top
11471     89/<- %ebx 4/r32/esp
11472     # convert
11473     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
11474     # check result->name
11475     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
11476     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
11477     # var inouts/edx: (addr list var) = lookup(result->inouts)
11478     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
11479     89/<- %edx 0/r32/eax
11480 $test-function-header-with-multiple-args:inout0:
11481     # var v/ebx: (addr var) = lookup(inouts->value)
11482     (lookup *edx *(edx+4))  # List-value List-value => eax
11483     89/<- %ebx 0/r32/eax
11484     # check v->name
11485     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11486     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
11487     # check v->type
11488     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11489     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
11490     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
11491     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
11492 $test-function-header-with-multiple-args:inout1:
11493     # inouts = lookup(inouts->next)
11494     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11495     89/<- %edx 0/r32/eax
11496     # v = lookup(inouts->value)
11497     (lookup *edx *(edx+4))  # List-value List-value => eax
11498     89/<- %ebx 0/r32/eax
11499     # check v->name
11500     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11501     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
11502     # check v->type
11503     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11504     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
11505     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
11506     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
11507 $test-function-header-with-multiple-args:inout2:
11508     # inouts = lookup(inouts->next)
11509     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11510     89/<- %edx 0/r32/eax
11511     # v = lookup(inouts->value)
11512     (lookup *edx *(edx+4))  # List-value List-value => eax
11513     89/<- %ebx 0/r32/eax
11514     # check v->name
11515     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11516     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
11517     # check v->type
11518     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11519     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
11520     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
11521     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
11522     # . epilogue
11523     89/<- %esp 5/r32/ebp
11524     5d/pop-to-ebp
11525     c3/return
11526 
11527 test-function-header-with-multiple-args-and-outputs:
11528     # . prologue
11529     55/push-ebp
11530     89/<- %ebp 4/r32/esp
11531     # setup
11532     8b/-> *Primitive-type-ids 0/r32/eax
11533     89/<- *Type-id 0/r32/eax  # stream-write
11534     (clear-stream _test-input-stream)
11535     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
11536     # result/ecx: function
11537     2b/subtract *Function-size 4/r32/esp
11538     89/<- %ecx 4/r32/esp
11539     (zero-out %ecx *Function-size)
11540     # var vars/ebx: (stack live-var 16)
11541     81 5/subop/subtract %esp 0xc0/imm32
11542     68/push 0xc0/imm32/size
11543     68/push 0/imm32/top
11544     89/<- %ebx 4/r32/esp
11545     # convert
11546     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
11547     # check result->name
11548     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
11549     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
11550     # var inouts/edx: (addr list var) = lookup(result->inouts)
11551     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
11552     89/<- %edx 0/r32/eax
11553 $test-function-header-with-multiple-args-and-outputs:inout0:
11554     # var v/ebx: (addr var) = lookup(inouts->value)
11555     (lookup *edx *(edx+4))  # List-value List-value => eax
11556     89/<- %ebx 0/r32/eax
11557     # check v->name
11558     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11559     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
11560     # check v->type
11561     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11562     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
11563     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
11564     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
11565 $test-function-header-with-multiple-args-and-outputs:inout1:
11566     # inouts = lookup(inouts->next)
11567     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11568     89/<- %edx 0/r32/eax
11569     # v = lookup(inouts->value)
11570     (lookup *edx *(edx+4))  # List-value List-value => eax
11571     89/<- %ebx 0/r32/eax
11572     # check v->name
11573     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11574     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
11575     # check v->type
11576     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11577     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
11578     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
11579     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
11580 $test-function-header-with-multiple-args-and-outputs:inout2:
11581     # inouts = lookup(inouts->next)
11582     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11583     89/<- %edx 0/r32/eax
11584     # v = lookup(inouts->value)
11585     (lookup *edx *(edx+4))  # List-value List-value => eax
11586     89/<- %ebx 0/r32/eax
11587     # check v->name
11588     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11589     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
11590     # check v->type
11591     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11592     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
11593     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
11594     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
11595 $test-function-header-with-multiple-args-and-outputs:out0:
11596     # var outputs/edx: (addr list var) = lookup(result->outputs)
11597     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
11598     89/<- %edx 0/r32/eax
11599     # v = lookup(outputs->value)
11600     (lookup *edx *(edx+4))  # List-value List-value => eax
11601     89/<- %ebx 0/r32/eax
11602     # check v->name
11603     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11604     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
11605     # check v->register
11606     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
11607     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
11608     # check v->type
11609     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11610     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
11611     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
11612     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
11613 $test-function-header-with-multiple-args-and-outputs:out1:
11614     # outputs = lookup(outputs->next)
11615     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11616     89/<- %edx 0/r32/eax
11617     # v = lookup(inouts->value)
11618     (lookup *edx *(edx+4))  # List-value List-value => eax
11619     89/<- %ebx 0/r32/eax
11620     # check v->name
11621     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11622     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
11623     # check v->register
11624     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
11625     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
11626     # check v->type
11627     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11628     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
11629     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
11630     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
11631     # . epilogue
11632     89/<- %esp 5/r32/ebp
11633     5d/pop-to-ebp
11634     c3/return
11635 
11636 # format for variables with types
11637 #   x: int
11638 #   x: int,
11639 #   x/eax: int
11640 #   x/eax: int,
11641 # ignores at most one trailing comma
11642 # WARNING: modifies name
11643 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
11644     # pseudocode:
11645     #   var s: slice
11646     #   if (!slice-ends-with(name, ":"))
11647     #     abort
11648     #   --name->end to skip ':'
11649     #   next-token-from-slice(name->start, name->end, '/', s)
11650     #   new-var-from-slice(s, out)
11651     #   ## register
11652     #   next-token-from-slice(s->end, name->end, '/', s)
11653     #   if (!slice-empty?(s))
11654     #     out->register = slice-to-string(s)
11655     #   ## type
11656     #   var type: (handle type-tree) = parse-type(first-line)
11657     #   out->type = type
11658     #
11659     # . prologue
11660     55/push-ebp
11661     89/<- %ebp 4/r32/esp
11662     # . save registers
11663     50/push-eax
11664     51/push-ecx
11665     52/push-edx
11666     53/push-ebx
11667     56/push-esi
11668     57/push-edi
11669     # esi = name
11670     8b/-> *(ebp+8) 6/r32/esi
11671     # if (!slice-ends-with?(name, ":")) abort
11672     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
11673     49/decrement-ecx
11674     8a/copy-byte *ecx 1/r32/CL
11675     81 4/subop/and %ecx 0xff/imm32
11676     81 7/subop/compare %ecx 0x3a/imm32/colon
11677     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
11678     # --name->end to skip ':'
11679     ff 1/subop/decrement *(esi+4)
11680     # var s/ecx: slice
11681     68/push 0/imm32/end
11682     68/push 0/imm32/start
11683     89/<- %ecx 4/r32/esp
11684 $parse-var-with-type:parse-name:
11685     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
11686 $parse-var-with-type:create-var:
11687     # new-var-from-slice(s, out)
11688     (new-var-from-slice Heap %ecx *(ebp+0x10))
11689     # save out->register
11690 $parse-var-with-type:save-register:
11691     # . var out-addr/edi: (addr var) = lookup(*out)
11692     8b/-> *(ebp+0x10) 7/r32/edi
11693     (lookup *edi *(edi+4))  # => eax
11694     89/<- %edi 0/r32/eax
11695     # . s = next-token(...)
11696     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
11697     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
11698     {
11699 $parse-var-with-type:write-register:
11700       (slice-empty? %ecx)  # => eax
11701       3d/compare-eax-and 0/imm32/false
11702       75/jump-if-!= break/disp8
11703       # out->register = slice-to-string(s)
11704       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
11705       (slice-to-string Heap %ecx %eax)
11706     }
11707 $parse-var-with-type:save-type:
11708     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
11709     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11710 $parse-var-with-type:end:
11711     # . reclaim locals
11712     81 0/subop/add %esp 8/imm32
11713     # . restore registers
11714     5f/pop-to-edi
11715     5e/pop-to-esi
11716     5b/pop-to-ebx
11717     5a/pop-to-edx
11718     59/pop-to-ecx
11719     58/pop-to-eax
11720     # . epilogue
11721     89/<- %esp 5/r32/ebp
11722     5d/pop-to-ebp
11723     c3/return
11724 
11725 $parse-var-with-type:abort:
11726     # error("var should have form 'name: type' in '" line "'\n")
11727     (write-buffered *(ebp+0x14) "var should have form 'name: type' in '")
11728     (flush *(ebp+0x14))
11729     (rewind-stream *(ebp+0xc))
11730     (write-stream-data *(ebp+0x14) *(ebp+0xc))
11731     (write-buffered *(ebp+0x14) "'\n")
11732     (flush *(ebp+0x14))
11733     (stop *(ebp+0x18) 1)
11734     # never gets here
11735 
11736 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
11737     # pseudocode:
11738     #   var s: slice = next-mu-token(in)
11739     #   assert s != ""
11740     #   assert s != "->"
11741     #   assert s != "{"
11742     #   assert s != "}"
11743     #   if s == ")"
11744     #     return
11745     #   out = allocate(Type-tree)
11746     #   if s != "("
11747     #     HACK: if s is an int, parse and return it
11748     #     out->is-atom? = true
11749     #     if (s[0] == "_")
11750     #       out->value = type-parameter
11751     #       out->parameter-name = slice-to-string(ad, s)
11752     #     else
11753     #       out->value = pos-or-insert-slice(Type-id, s)
11754     #     return
11755     #   out->left = parse-type(ad, in)
11756     #   out->right = parse-type-tree(ad, in)
11757     #
11758     # . prologue
11759     55/push-ebp
11760     89/<- %ebp 4/r32/esp
11761     # . save registers
11762     50/push-eax
11763     51/push-ecx
11764     52/push-edx
11765     # clear out
11766     (zero-out *(ebp+0x10) *Handle-size)
11767     # var s/ecx: slice
11768     68/push 0/imm32
11769     68/push 0/imm32
11770     89/<- %ecx 4/r32/esp
11771     # s = next-mu-token(in)
11772     (next-mu-token *(ebp+0xc) %ecx)
11773 #?     (write-buffered Stderr "tok: ")
11774 #?     (write-slice-buffered Stderr %ecx)
11775 #?     (write-buffered Stderr "$\n")
11776 #?     (flush Stderr)
11777     # assert s != ""
11778     (slice-equal? %ecx "")  # => eax
11779     3d/compare-eax-and 0/imm32/false
11780     0f 85/jump-if-!= $parse-type:abort/disp32
11781     # assert s != "{"
11782     (slice-equal? %ecx "{")  # => eax
11783     3d/compare-eax-and 0/imm32/false
11784     0f 85/jump-if-!= $parse-type:abort/disp32
11785     # assert s != "}"
11786     (slice-equal? %ecx "}")  # => eax
11787     3d/compare-eax-and 0/imm32/false
11788     0f 85/jump-if-!= $parse-type:abort/disp32
11789     # assert s != "->"
11790     (slice-equal? %ecx "->")  # => eax
11791     3d/compare-eax-and 0/imm32/false
11792     0f 85/jump-if-!= $parse-type:abort/disp32
11793     # if (s == ")") return
11794     (slice-equal? %ecx ")")  # => eax
11795     3d/compare-eax-and 0/imm32/false
11796     0f 85/jump-if-!= $parse-type:end/disp32
11797     # out = new tree
11798     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
11799     # var out-addr/edx: (addr type-tree) = lookup(*out)
11800     8b/-> *(ebp+0x10) 2/r32/edx
11801     (lookup *edx *(edx+4))  # => eax
11802     89/<- %edx 0/r32/eax
11803     {
11804       # if (s != "(") break
11805       (slice-equal? %ecx "(")  # => eax
11806       3d/compare-eax-and 0/imm32/false
11807       0f 85/jump-if-!= break/disp32
11808       # if s is a number, store it in the type's size field
11809       {
11810 $parse-type:check-for-int:
11811         # var tmp/eax: byte = *s->slice
11812         8b/-> *ecx 0/r32/eax
11813         8a/copy-byte *eax 0/r32/AL
11814         81 4/subop/and %eax 0xff/imm32
11815         # TODO: raise an error on `var x: (array int a)`
11816         (is-decimal-digit? %eax)  # => eax
11817         3d/compare-eax-and 0/imm32/false
11818         74/jump-if-= break/disp8
11819         #
11820         (is-hex-int? %ecx)  # => eax
11821         3d/compare-eax-and 0/imm32/false
11822         74/jump-if-= break/disp8
11823 $parse-type:int:
11824         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
11825         (parse-hex-int-from-slice %ecx)  # => eax
11826         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
11827         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
11828         e9/jump $parse-type:end/disp32
11829       }
11830 $parse-type:atom:
11831       # out->is-atom? = true
11832       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
11833       {
11834 $parse-type:check-for-type-parameter:
11835         # var tmp/eax: byte = *s->slice
11836         8b/-> *ecx 0/r32/eax
11837         8a/copy-byte *eax 0/r32/AL
11838         81 4/subop/and %eax 0xff/imm32
11839         # if (tmp != '_') break
11840         3d/compare-eax-and 0x5f/imm32/_
11841         75/jump-if-!= break/disp8
11842 $parse-type:type-parameter:
11843         # out->value = type-parameter
11844         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
11845         # out->parameter-name = slice-to-string(ad, s)
11846         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
11847         (slice-to-string *(ebp+8) %ecx %eax)
11848         e9/jump $parse-type:end/disp32
11849       }
11850 $parse-type:non-type-parameter:
11851       # out->value = pos-or-insert-slice(Type-id, s)
11852       (pos-or-insert-slice Type-id %ecx)  # => eax
11853       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
11854       e9/jump $parse-type:end/disp32
11855     }
11856 $parse-type:non-atom:
11857     # otherwise s == "("
11858     # out->left = parse-type(ad, in)
11859     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
11860     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11861     # out->right = parse-type-tree(ad, in)
11862     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
11863     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11864 $parse-type:end:
11865     # . reclaim locals
11866     81 0/subop/add %esp 8/imm32
11867     # . restore registers
11868     5a/pop-to-edx
11869     59/pop-to-ecx
11870     58/pop-to-eax
11871     # . epilogue
11872     89/<- %esp 5/r32/ebp
11873     5d/pop-to-ebp
11874     c3/return
11875 
11876 $parse-type:abort:
11877     # error("unexpected token when parsing type: '" s "'\n")
11878     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
11879     (write-slice-buffered *(ebp+0x14) %ecx)
11880     (write-buffered *(ebp+0x14) "'\n")
11881     (flush *(ebp+0x14))
11882     (stop *(ebp+0x18) 1)
11883     # never gets here
11884 
11885 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
11886     # pseudocode:
11887     #   var tmp: (handle type-tree) = parse-type(ad, in)
11888     #   if tmp == 0
11889     #     return 0
11890     #   out = allocate(Type-tree)
11891     #   out->left = tmp
11892     #   out->right = parse-type-tree(ad, in)
11893     #
11894     # . prologue
11895     55/push-ebp
11896     89/<- %ebp 4/r32/esp
11897     # . save registers
11898     50/push-eax
11899     51/push-ecx
11900     52/push-edx
11901     #
11902     (zero-out *(ebp+0x10) *Handle-size)
11903     # var tmp/ecx: (handle type-tree)
11904     68/push 0/imm32
11905     68/push 0/imm32
11906     89/<- %ecx 4/r32/esp
11907     # tmp = parse-type(ad, in)
11908     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
11909     # if (tmp == 0) return
11910     81 7/subop/compare *ecx 0/imm32
11911     74/jump-if-= $parse-type-tree:end/disp8
11912     # out = new tree
11913     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
11914     # var out-addr/edx: (addr tree) = lookup(*out)
11915     8b/-> *(ebp+0x10) 2/r32/edx
11916     (lookup *edx *(edx+4))  # => eax
11917     89/<- %edx 0/r32/eax
11918     # out->left = tmp
11919     8b/-> *ecx 0/r32/eax
11920     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
11921     8b/-> *(ecx+4) 0/r32/eax
11922     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
11923     # out->right = parse-type-tree(ad, in)
11924     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
11925     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11926 $parse-type-tree:end:
11927     # . reclaim locals
11928     81 0/subop/add %esp 8/imm32
11929     # . restore registers
11930     5a/pop-to-edx
11931     59/pop-to-ecx
11932     58/pop-to-eax
11933     # . epilogue
11934     89/<- %esp 5/r32/ebp
11935     5d/pop-to-ebp
11936     c3/return
11937 
11938 next-mu-token:  # in: (addr stream byte), out: (addr slice)
11939     # pseudocode:
11940     # start:
11941     #   skip-chars-matching-whitespace(in)
11942     #   if in->read >= in->write              # end of in
11943     #     out = {0, 0}
11944     #     return
11945     #   out->start = &in->data[in->read]
11946     #   var curr-byte/eax: byte = in->data[in->read]
11947     #   if curr->byte == ','                  # comment token
11948     #     ++in->read
11949     #     goto start
11950     #   if curr-byte == '#'                   # comment
11951     #     goto done                             # treat as eof
11952     #   if curr-byte == '"'                   # string literal
11953     #     skip-string(in)
11954     #     goto done                           # no metadata
11955     #   if curr-byte == '('
11956     #     ++in->read
11957     #     goto done
11958     #   if curr-byte == ')'
11959     #     ++in->read
11960     #     goto done
11961     #   # read a word
11962     #   while true
11963     #     if in->read >= in->write
11964     #       break
11965     #     curr-byte = in->data[in->read]
11966     #     if curr-byte == ' '
11967     #       break
11968     #     if curr-byte == '\r'
11969     #       break
11970     #     if curr-byte == '\n'
11971     #       break
11972     #     if curr-byte == '('
11973     #       break
11974     #     if curr-byte == ')'
11975     #       break
11976     #     if curr-byte == ','
11977     #       break
11978     #     ++in->read
11979     # done:
11980     #   out->end = &in->data[in->read]
11981     #
11982     # . prologue
11983     55/push-ebp
11984     89/<- %ebp 4/r32/esp
11985     # . save registers
11986     50/push-eax
11987     51/push-ecx
11988     56/push-esi
11989     57/push-edi
11990     # esi = in
11991     8b/-> *(ebp+8) 6/r32/esi
11992     # edi = out
11993     8b/-> *(ebp+0xc) 7/r32/edi
11994 $next-mu-token:start:
11995     (skip-chars-matching-whitespace %esi)
11996 $next-mu-token:check0:
11997     # if (in->read >= in->write) return out = {0, 0}
11998     # . ecx = in->read
11999     8b/-> *(esi+4) 1/r32/ecx
12000     # . if (ecx >= in->write) return out = {0, 0}
12001     3b/compare<- *esi 1/r32/ecx
12002     c7 0/subop/copy *edi 0/imm32
12003     c7 0/subop/copy *(edi+4) 0/imm32
12004     0f 8d/jump-if->= $next-mu-token:end/disp32
12005     # out->start = &in->data[in->read]
12006     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
12007     89/<- *edi 0/r32/eax
12008     # var curr-byte/eax: byte = in->data[in->read]
12009     31/xor-with %eax 0/r32/eax
12010     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
12011     {
12012 $next-mu-token:check-for-comma:
12013       # if (curr-byte != ',') break
12014       3d/compare-eax-and 0x2c/imm32/comma
12015       75/jump-if-!= break/disp8
12016       # ++in->read
12017       ff 0/subop/increment *(esi+4)
12018       # restart
12019       e9/jump $next-mu-token:start/disp32
12020     }
12021     {
12022 $next-mu-token:check-for-comment:
12023       # if (curr-byte != '#') break
12024       3d/compare-eax-and 0x23/imm32/pound
12025       75/jump-if-!= break/disp8
12026       # return eof
12027       e9/jump $next-mu-token:done/disp32
12028     }
12029     {
12030 $next-mu-token:check-for-string-literal:
12031       # if (curr-byte != '"') break
12032       3d/compare-eax-and 0x22/imm32/dquote
12033       75/jump-if-!= break/disp8
12034       (skip-string %esi)
12035       # return
12036       e9/jump $next-mu-token:done/disp32
12037     }
12038     {
12039 $next-mu-token:check-for-open-paren:
12040       # if (curr-byte != '(') break
12041       3d/compare-eax-and 0x28/imm32/open-paren
12042       75/jump-if-!= break/disp8
12043       # ++in->read
12044       ff 0/subop/increment *(esi+4)
12045       # return
12046       e9/jump $next-mu-token:done/disp32
12047     }
12048     {
12049 $next-mu-token:check-for-close-paren:
12050       # if (curr-byte != ')') break
12051       3d/compare-eax-and 0x29/imm32/close-paren
12052       75/jump-if-!= break/disp8
12053       # ++in->read
12054       ff 0/subop/increment *(esi+4)
12055       # return
12056       e9/jump $next-mu-token:done/disp32
12057     }
12058     {
12059 $next-mu-token:regular-word-without-metadata:
12060       # if (in->read >= in->write) break
12061       # . ecx = in->read
12062       8b/-> *(esi+4) 1/r32/ecx
12063       # . if (ecx >= in->write) break
12064       3b/compare<- *esi 1/r32/ecx
12065       7d/jump-if->= break/disp8
12066       # var c/eax: byte = in->data[in->read]
12067       31/xor-with %eax 0/r32/eax
12068       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
12069       # if (c == ' ') break
12070       3d/compare-eax-and 0x20/imm32/space
12071       74/jump-if-= break/disp8
12072       # if (c == '\r') break
12073       3d/compare-eax-and 0xd/imm32/carriage-return
12074       74/jump-if-= break/disp8
12075       # if (c == '\n') break
12076       3d/compare-eax-and 0xa/imm32/newline
12077       74/jump-if-= break/disp8
12078       # if (c == '(') break
12079       3d/compare-eax-and 0x28/imm32/open-paren
12080       0f 84/jump-if-= break/disp32
12081       # if (c == ')') break
12082       3d/compare-eax-and 0x29/imm32/close-paren
12083       0f 84/jump-if-= break/disp32
12084       # if (c == ',') break
12085       3d/compare-eax-and 0x2c/imm32/comma
12086       0f 84/jump-if-= break/disp32
12087       # ++in->read
12088       ff 0/subop/increment *(esi+4)
12089       #
12090       e9/jump loop/disp32
12091     }
12092 $next-mu-token:done:
12093     # out->end = &in->data[in->read]
12094     8b/-> *(esi+4) 1/r32/ecx
12095     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
12096     89/<- *(edi+4) 0/r32/eax
12097 $next-mu-token:end:
12098     # . restore registers
12099     5f/pop-to-edi
12100     5e/pop-to-esi
12101     59/pop-to-ecx
12102     58/pop-to-eax
12103     # . epilogue
12104     89/<- %esp 5/r32/ebp
12105     5d/pop-to-ebp
12106     c3/return
12107 
12108 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
12109     # . prologue
12110     55/push-ebp
12111     89/<- %ebp 4/r32/esp
12112     # if (pos-slice(arr, s) != -1) return it
12113     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
12114     3d/compare-eax-and -1/imm32
12115     75/jump-if-!= $pos-or-insert-slice:end/disp8
12116 $pos-or-insert-slice:insert:
12117     # var s2/eax: (handle array byte)
12118     68/push 0/imm32
12119     68/push 0/imm32
12120     89/<- %eax 4/r32/esp
12121     (slice-to-string Heap *(ebp+0xc) %eax)
12122     # throw away alloc-id
12123     (lookup *eax *(eax+4))  # => eax
12124     (write-int *(ebp+8) %eax)
12125     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
12126 $pos-or-insert-slice:end:
12127     # . reclaim locals
12128     81 0/subop/add %esp 8/imm32
12129     # . epilogue
12130     89/<- %esp 5/r32/ebp
12131     5d/pop-to-ebp
12132     c3/return
12133 
12134 # return the index in an array of strings matching 's', -1 if not found
12135 # index is denominated in elements, not bytes
12136 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
12137     # . prologue
12138     55/push-ebp
12139     89/<- %ebp 4/r32/esp
12140     # . save registers
12141     51/push-ecx
12142     52/push-edx
12143     53/push-ebx
12144     56/push-esi
12145 #?     (write-buffered Stderr "pos-slice: ")
12146 #?     (write-slice-buffered Stderr *(ebp+0xc))
12147 #?     (write-buffered Stderr "\n")
12148 #?     (flush Stderr)
12149     # esi = arr
12150     8b/-> *(ebp+8) 6/r32/esi
12151     # var index/ecx: int = 0
12152     b9/copy-to-ecx 0/imm32
12153     # var curr/edx: (addr (addr array byte)) = arr->data
12154     8d/copy-address *(esi+0xc) 2/r32/edx
12155     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
12156     8b/-> *esi 3/r32/ebx
12157     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
12158     {
12159 #?       (write-buffered Stderr "  ")
12160 #?       (write-int32-hex-buffered Stderr %ecx)
12161 #?       (write-buffered Stderr "\n")
12162 #?       (flush Stderr)
12163       # if (curr >= max) return -1
12164       39/compare %edx 3/r32/ebx
12165       b8/copy-to-eax -1/imm32
12166       73/jump-if-addr>= $pos-slice:end/disp8
12167       # if (slice-equal?(s, *curr)) break
12168       (slice-equal? *(ebp+0xc) *edx)  # => eax
12169       3d/compare-eax-and 0/imm32/false
12170       75/jump-if-!= break/disp8
12171       # ++index
12172       41/increment-ecx
12173       # curr += 4
12174       81 0/subop/add %edx 4/imm32
12175       #
12176       eb/jump loop/disp8
12177     }
12178     # return index
12179     89/<- %eax 1/r32/ecx
12180 $pos-slice:end:
12181 #?     (write-buffered Stderr "=> ")
12182 #?     (write-int32-hex-buffered Stderr %eax)
12183 #?     (write-buffered Stderr "\n")
12184     # . restore registers
12185     5e/pop-to-esi
12186     5b/pop-to-ebx
12187     5a/pop-to-edx
12188     59/pop-to-ecx
12189     # . epilogue
12190     89/<- %esp 5/r32/ebp
12191     5d/pop-to-ebp
12192     c3/return
12193 
12194 test-parse-var-with-type:
12195     # . prologue
12196     55/push-ebp
12197     89/<- %ebp 4/r32/esp
12198     # setup
12199     8b/-> *Primitive-type-ids 0/r32/eax
12200     89/<- *Type-id 0/r32/eax  # stream-write
12201     # (eax..ecx) = "x:"
12202     b8/copy-to-eax "x:"/imm32
12203     8b/-> *eax 1/r32/ecx
12204     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12205     05/add-to-eax 4/imm32
12206     # var slice/ecx: slice = {eax, ecx}
12207     51/push-ecx
12208     50/push-eax
12209     89/<- %ecx 4/r32/esp
12210     # _test-input-stream contains "int"
12211     (clear-stream _test-input-stream)
12212     (write _test-input-stream "int")
12213     # var v/edx: (handle var)
12214     68/push 0/imm32
12215     68/push 0/imm32
12216     89/<- %edx 4/r32/esp
12217     #
12218     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
12219     # var v-addr/edx: (addr var) = lookup(v)
12220     (lookup *edx *(edx+4))  # => eax
12221     89/<- %edx 0/r32/eax
12222     # check v-addr->name
12223     (lookup *edx *(edx+4))  # Var-name Var-name => eax
12224     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
12225     # check v-addr->type
12226     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
12227     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
12228     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
12229     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
12230     # . epilogue
12231     89/<- %esp 5/r32/ebp
12232     5d/pop-to-ebp
12233     c3/return
12234 
12235 test-parse-var-with-type-and-register:
12236     # . prologue
12237     55/push-ebp
12238     89/<- %ebp 4/r32/esp
12239     # setup
12240     8b/-> *Primitive-type-ids 0/r32/eax
12241     89/<- *Type-id 0/r32/eax  # stream-write
12242     # (eax..ecx) = "x/eax:"
12243     b8/copy-to-eax "x/eax:"/imm32
12244     8b/-> *eax 1/r32/ecx
12245     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12246     05/add-to-eax 4/imm32
12247     # var slice/ecx: slice = {eax, ecx}
12248     51/push-ecx
12249     50/push-eax
12250     89/<- %ecx 4/r32/esp
12251     # _test-input-stream contains "int"
12252     (clear-stream _test-input-stream)
12253     (write _test-input-stream "int")
12254     # var v/edx: (handle var)
12255     68/push 0/imm32
12256     68/push 0/imm32
12257     89/<- %edx 4/r32/esp
12258     #
12259     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
12260     # var v-addr/edx: (addr var) = lookup(v)
12261     (lookup *edx *(edx+4))  # => eax
12262     89/<- %edx 0/r32/eax
12263     # check v-addr->name
12264     (lookup *edx *(edx+4))  # Var-name Var-name => eax
12265     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
12266     # check v-addr->register
12267     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
12268     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
12269     # check v-addr->type
12270     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
12271     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
12272     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
12273     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
12274     # . epilogue
12275     89/<- %esp 5/r32/ebp
12276     5d/pop-to-ebp
12277     c3/return
12278 
12279 test-parse-var-with-trailing-characters:
12280     # . prologue
12281     55/push-ebp
12282     89/<- %ebp 4/r32/esp
12283     # setup
12284     8b/-> *Primitive-type-ids 0/r32/eax
12285     89/<- *Type-id 0/r32/eax  # stream-write
12286     # (eax..ecx) = "x:"
12287     b8/copy-to-eax "x:"/imm32
12288     8b/-> *eax 1/r32/ecx
12289     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12290     05/add-to-eax 4/imm32
12291     # var slice/ecx: slice = {eax, ecx}
12292     51/push-ecx
12293     50/push-eax
12294     89/<- %ecx 4/r32/esp
12295     # _test-input-stream contains "int,"
12296     (clear-stream _test-input-stream)
12297     (write _test-input-stream "int,")
12298     # var v/edx: (handle var)
12299     68/push 0/imm32
12300     68/push 0/imm32
12301     89/<- %edx 4/r32/esp
12302     #
12303     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
12304     # var v-addr/edx: (addr var) = lookup(v)
12305     (lookup *edx *(edx+4))  # => eax
12306     89/<- %edx 0/r32/eax
12307     # check v-addr->name
12308     (lookup *edx *(edx+4))  # Var-name Var-name => eax
12309     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
12310     # check v-addr->register
12311     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
12312     # check v-addr->type
12313     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
12314     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
12315     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
12316     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
12317     # . epilogue
12318     89/<- %esp 5/r32/ebp
12319     5d/pop-to-ebp
12320     c3/return
12321 
12322 test-parse-var-with-register-and-trailing-characters:
12323     # . prologue
12324     55/push-ebp
12325     89/<- %ebp 4/r32/esp
12326     # setup
12327     8b/-> *Primitive-type-ids 0/r32/eax
12328     89/<- *Type-id 0/r32/eax  # stream-write
12329     # (eax..ecx) = "x/eax:"
12330     b8/copy-to-eax "x/eax:"/imm32
12331     8b/-> *eax 1/r32/ecx
12332     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12333     05/add-to-eax 4/imm32
12334     # var slice/ecx: slice = {eax, ecx}
12335     51/push-ecx
12336     50/push-eax
12337     89/<- %ecx 4/r32/esp
12338     # _test-input-stream contains "int,"
12339     (clear-stream _test-input-stream)
12340     (write _test-input-stream "int,")
12341     # var v/edx: (handle var)
12342     68/push 0/imm32
12343     68/push 0/imm32
12344     89/<- %edx 4/r32/esp
12345     #
12346     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
12347     # var v-addr/edx: (addr var) = lookup(v)
12348     (lookup *edx *(edx+4))  # => eax
12349     89/<- %edx 0/r32/eax
12350     # check v-addr->name
12351     (lookup *edx *(edx+4))  # Var-name Var-name => eax
12352     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
12353     # check v-addr->register
12354     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
12355     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
12356     # check v-addr->type
12357     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
12358     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
12359     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
12360     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
12361     # . epilogue
12362     89/<- %esp 5/r32/ebp
12363     5d/pop-to-ebp
12364     c3/return
12365 
12366 test-parse-var-with-compound-type:
12367     # . prologue
12368     55/push-ebp
12369     89/<- %ebp 4/r32/esp
12370     # setup
12371     8b/-> *Primitive-type-ids 0/r32/eax
12372     89/<- *Type-id 0/r32/eax  # stream-write
12373     # (eax..ecx) = "x:"
12374     b8/copy-to-eax "x:"/imm32
12375     8b/-> *eax 1/r32/ecx
12376     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12377     05/add-to-eax 4/imm32
12378     # var slice/ecx: slice = {eax, ecx}
12379     51/push-ecx
12380     50/push-eax
12381     89/<- %ecx 4/r32/esp
12382     # _test-input-stream contains "(addr int)"
12383     (clear-stream _test-input-stream)
12384     (write _test-input-stream "(addr int)")
12385     # var v/edx: (handle var)
12386     68/push 0/imm32
12387     68/push 0/imm32
12388     89/<- %edx 4/r32/esp
12389     #
12390     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
12391     # var v-addr/edx: (addr var) = lookup(v)
12392     (lookup *edx *(edx+4))  # => eax
12393     89/<- %edx 0/r32/eax
12394     # check v-addr->name
12395     (lookup *edx *(edx+4))  # Var-name Var-name => eax
12396     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
12397     # check v-addr->register
12398     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
12399     # - check v-addr->type
12400     # var type/edx: (addr type-tree) = var->type
12401     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
12402     89/<- %edx 0/r32/eax
12403     # type is a non-atom
12404     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
12405     # type->left == atom(addr)
12406     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
12407     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
12408     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
12409     # type->right->left == atom(int)
12410     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
12411     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
12412     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
12413     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
12414     # type->right->right == null
12415     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
12416     # . epilogue
12417     89/<- %esp 5/r32/ebp
12418     5d/pop-to-ebp
12419     c3/return
12420 
12421 # identifier starts with a letter or '$' or '_'
12422 # no constraints at the moment on later letters
12423 # all we really want to do so far is exclude '{', '}' and '->'
12424 is-identifier?:  # in: (addr slice) -> result/eax: boolean
12425     # . prologue
12426     55/push-ebp
12427     89/<- %ebp 4/r32/esp
12428     # if (slice-empty?(in)) return false
12429     (slice-empty? *(ebp+8))  # => eax
12430     3d/compare-eax-and 0/imm32/false
12431     75/jump-if-!= $is-identifier?:false/disp8
12432     # var c/eax: byte = *in->start
12433     8b/-> *(ebp+8) 0/r32/eax
12434     8b/-> *eax 0/r32/eax
12435     8a/copy-byte *eax 0/r32/AL
12436     81 4/subop/and %eax 0xff/imm32
12437     # if (c == '$') return true
12438     3d/compare-eax-and 0x24/imm32/$
12439     74/jump-if-= $is-identifier?:true/disp8
12440     # if (c == '_') return true
12441     3d/compare-eax-and 0x5f/imm32/_
12442     74/jump-if-= $is-identifier?:true/disp8
12443     # drop case
12444     25/and-eax-with 0x5f/imm32
12445     # if (c < 'A') return false
12446     3d/compare-eax-and 0x41/imm32/A
12447     7c/jump-if-< $is-identifier?:false/disp8
12448     # if (c > 'Z') return false
12449     3d/compare-eax-and 0x5a/imm32/Z
12450     7f/jump-if-> $is-identifier?:false/disp8
12451     # otherwise return true
12452 $is-identifier?:true:
12453     b8/copy-to-eax 1/imm32/true
12454     eb/jump $is-identifier?:end/disp8
12455 $is-identifier?:false:
12456     b8/copy-to-eax 0/imm32/false
12457 $is-identifier?:end:
12458     # . epilogue
12459     89/<- %esp 5/r32/ebp
12460     5d/pop-to-ebp
12461     c3/return
12462 
12463 test-is-identifier-dollar:
12464     # . prologue
12465     55/push-ebp
12466     89/<- %ebp 4/r32/esp
12467     # (eax..ecx) = "$a"
12468     b8/copy-to-eax "$a"/imm32
12469     8b/-> *eax 1/r32/ecx
12470     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12471     05/add-to-eax 4/imm32
12472     # var slice/ecx: slice = {eax, ecx}
12473     51/push-ecx
12474     50/push-eax
12475     89/<- %ecx 4/r32/esp
12476     #
12477     (is-identifier? %ecx)
12478     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
12479     # . epilogue
12480     89/<- %esp 5/r32/ebp
12481     5d/pop-to-ebp
12482     c3/return
12483 
12484 test-is-identifier-underscore:
12485     # . prologue
12486     55/push-ebp
12487     89/<- %ebp 4/r32/esp
12488     # (eax..ecx) = "_a"
12489     b8/copy-to-eax "_a"/imm32
12490     8b/-> *eax 1/r32/ecx
12491     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12492     05/add-to-eax 4/imm32
12493     # var slice/ecx: slice = {eax, ecx}
12494     51/push-ecx
12495     50/push-eax
12496     89/<- %ecx 4/r32/esp
12497     #
12498     (is-identifier? %ecx)
12499     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
12500     # . epilogue
12501     89/<- %esp 5/r32/ebp
12502     5d/pop-to-ebp
12503     c3/return
12504 
12505 test-is-identifier-a:
12506     # . prologue
12507     55/push-ebp
12508     89/<- %ebp 4/r32/esp
12509     # (eax..ecx) = "a$"
12510     b8/copy-to-eax "a$"/imm32
12511     8b/-> *eax 1/r32/ecx
12512     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12513     05/add-to-eax 4/imm32
12514     # var slice/ecx: slice = {eax, ecx}
12515     51/push-ecx
12516     50/push-eax
12517     89/<- %ecx 4/r32/esp
12518     #
12519     (is-identifier? %ecx)
12520     (check-ints-equal %eax 1 "F - test-is-identifier-a")
12521     # . epilogue
12522     89/<- %esp 5/r32/ebp
12523     5d/pop-to-ebp
12524     c3/return
12525 
12526 test-is-identifier-z:
12527     # . prologue
12528     55/push-ebp
12529     89/<- %ebp 4/r32/esp
12530     # (eax..ecx) = "z$"
12531     b8/copy-to-eax "z$"/imm32
12532     8b/-> *eax 1/r32/ecx
12533     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12534     05/add-to-eax 4/imm32
12535     # var slice/ecx: slice = {eax, ecx}
12536     51/push-ecx
12537     50/push-eax
12538     89/<- %ecx 4/r32/esp
12539     #
12540     (is-identifier? %ecx)
12541     (check-ints-equal %eax 1 "F - test-is-identifier-z")
12542     # . epilogue
12543     89/<- %esp 5/r32/ebp
12544     5d/pop-to-ebp
12545     c3/return
12546 
12547 test-is-identifier-A:
12548     # . prologue
12549     55/push-ebp
12550     89/<- %ebp 4/r32/esp
12551     # (eax..ecx) = "A$"
12552     b8/copy-to-eax "A$"/imm32
12553     8b/-> *eax 1/r32/ecx
12554     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12555     05/add-to-eax 4/imm32
12556     # var slice/ecx: slice = {eax, ecx}
12557     51/push-ecx
12558     50/push-eax
12559     89/<- %ecx 4/r32/esp
12560     #
12561     (is-identifier? %ecx)
12562     (check-ints-equal %eax 1 "F - test-is-identifier-A")
12563     # . epilogue
12564     89/<- %esp 5/r32/ebp
12565     5d/pop-to-ebp
12566     c3/return
12567 
12568 test-is-identifier-Z:
12569     # . prologue
12570     55/push-ebp
12571     89/<- %ebp 4/r32/esp
12572     # (eax..ecx) = "Z$"
12573     b8/copy-to-eax "Z$"/imm32
12574     8b/-> *eax 1/r32/ecx
12575     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12576     05/add-to-eax 4/imm32
12577     # var slice/ecx: slice = {eax, ecx}
12578     51/push-ecx
12579     50/push-eax
12580     89/<- %ecx 4/r32/esp
12581     #
12582     (is-identifier? %ecx)
12583     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
12584     # . epilogue
12585     89/<- %esp 5/r32/ebp
12586     5d/pop-to-ebp
12587     c3/return
12588 
12589 test-is-identifier-at:
12590     # character before 'A' is invalid
12591     # . prologue
12592     55/push-ebp
12593     89/<- %ebp 4/r32/esp
12594     # (eax..ecx) = "@a"
12595     b8/copy-to-eax "@a"/imm32
12596     8b/-> *eax 1/r32/ecx
12597     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12598     05/add-to-eax 4/imm32
12599     # var slice/ecx: slice = {eax, ecx}
12600     51/push-ecx
12601     50/push-eax
12602     89/<- %ecx 4/r32/esp
12603     #
12604     (is-identifier? %ecx)
12605     (check-ints-equal %eax 0 "F - test-is-identifier-@")
12606     # . epilogue
12607     89/<- %esp 5/r32/ebp
12608     5d/pop-to-ebp
12609     c3/return
12610 
12611 test-is-identifier-square-bracket:
12612     # character after 'Z' is invalid
12613     # . prologue
12614     55/push-ebp
12615     89/<- %ebp 4/r32/esp
12616     # (eax..ecx) = "[a"
12617     b8/copy-to-eax "[a"/imm32
12618     8b/-> *eax 1/r32/ecx
12619     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12620     05/add-to-eax 4/imm32
12621     # var slice/ecx: slice = {eax, ecx}
12622     51/push-ecx
12623     50/push-eax
12624     89/<- %ecx 4/r32/esp
12625     #
12626     (is-identifier? %ecx)
12627     (check-ints-equal %eax 0 "F - test-is-identifier-@")
12628     # . epilogue
12629     89/<- %esp 5/r32/ebp
12630     5d/pop-to-ebp
12631     c3/return
12632 
12633 test-is-identifier-backtick:
12634     # character before 'a' is invalid
12635     # . prologue
12636     55/push-ebp
12637     89/<- %ebp 4/r32/esp
12638     # (eax..ecx) = "`a"
12639     b8/copy-to-eax "`a"/imm32
12640     8b/-> *eax 1/r32/ecx
12641     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12642     05/add-to-eax 4/imm32
12643     # var slice/ecx: slice = {eax, ecx}
12644     51/push-ecx
12645     50/push-eax
12646     89/<- %ecx 4/r32/esp
12647     #
12648     (is-identifier? %ecx)
12649     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
12650     # . epilogue
12651     89/<- %esp 5/r32/ebp
12652     5d/pop-to-ebp
12653     c3/return
12654 
12655 test-is-identifier-curly-brace-open:
12656     # character after 'z' is invalid; also used for blocks
12657     # . prologue
12658     55/push-ebp
12659     89/<- %ebp 4/r32/esp
12660     # (eax..ecx) = "{a"
12661     b8/copy-to-eax "{a"/imm32
12662     8b/-> *eax 1/r32/ecx
12663     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12664     05/add-to-eax 4/imm32
12665     # var slice/ecx: slice = {eax, ecx}
12666     51/push-ecx
12667     50/push-eax
12668     89/<- %ecx 4/r32/esp
12669     #
12670     (is-identifier? %ecx)
12671     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
12672     # . epilogue
12673     89/<- %esp 5/r32/ebp
12674     5d/pop-to-ebp
12675     c3/return
12676 
12677 test-is-identifier-curly-brace-close:
12678     # . prologue
12679     55/push-ebp
12680     89/<- %ebp 4/r32/esp
12681     # (eax..ecx) = "}a"
12682     b8/copy-to-eax "}a"/imm32
12683     8b/-> *eax 1/r32/ecx
12684     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12685     05/add-to-eax 4/imm32
12686     # var slice/ecx: slice = {eax, ecx}
12687     51/push-ecx
12688     50/push-eax
12689     89/<- %ecx 4/r32/esp
12690     #
12691     (is-identifier? %ecx)
12692     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
12693     # . epilogue
12694     89/<- %esp 5/r32/ebp
12695     5d/pop-to-ebp
12696     c3/return
12697 
12698 test-is-identifier-hyphen:
12699     # disallow leading '-' since '->' has special meaning
12700     # . prologue
12701     55/push-ebp
12702     89/<- %ebp 4/r32/esp
12703     # (eax..ecx) = "-a"
12704     b8/copy-to-eax "-a"/imm32
12705     8b/-> *eax 1/r32/ecx
12706     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12707     05/add-to-eax 4/imm32
12708     # var slice/ecx: slice = {eax, ecx}
12709     51/push-ecx
12710     50/push-eax
12711     89/<- %ecx 4/r32/esp
12712     #
12713     (is-identifier? %ecx)
12714     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
12715     # . epilogue
12716     89/<- %esp 5/r32/ebp
12717     5d/pop-to-ebp
12718     c3/return
12719 
12720 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
12721     # . prologue
12722     55/push-ebp
12723     89/<- %ebp 4/r32/esp
12724     # . save registers
12725     50/push-eax
12726     56/push-esi
12727     57/push-edi
12728     # esi = in
12729     8b/-> *(ebp+8) 6/r32/esi
12730     # edi = out
12731     8b/-> *(ebp+0xc) 7/r32/edi
12732     # initialize some global state
12733     c7 0/subop/copy *Curr-block-depth 1/imm32
12734     # parse-mu-block(in, vars, out, out->body)
12735     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
12736     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
12737 $populate-mu-function-body:end:
12738     # . restore registers
12739     5f/pop-to-edi
12740     5e/pop-to-esi
12741     58/pop-to-eax
12742     # . epilogue
12743     89/<- %esp 5/r32/ebp
12744     5d/pop-to-ebp
12745     c3/return
12746 
12747 # parses a block, assuming that the leading '{' has already been read by the caller
12748 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)
12749     # pseudocode:
12750     #   var line: (stream byte 512)
12751     #   var word-slice: slice
12752     #   allocate(Heap, Stmt-size, out)
12753     #   var out-addr: (addr block) = lookup(*out)
12754     #   out-addr->tag = 0/block
12755     #   out-addr->var = some unique name
12756     #   push(vars, {out-addr->var, false})
12757     #   while true                                  # line loop
12758     #     clear-stream(line)
12759     #     read-line-buffered(in, line)
12760     #     if (line->write == 0) break               # end of file
12761     #     word-slice = next-mu-token(line)
12762     #     if slice-empty?(word-slice)               # end of line
12763     #       continue
12764     #     else if slice-starts-with?(word-slice, "#")
12765     #       continue
12766     #     else if slice-equal?(word-slice, "{")
12767     #       assert(no-tokens-in(line))
12768     #       block = parse-mu-block(in, vars, fn)
12769     #       append-to-block(out-addr, block)
12770     #     else if slice-equal?(word-slice, "}")
12771     #       break
12772     #     else if slice-ends-with?(word-slice, ":")
12773     #       # TODO: error-check the rest of 'line'
12774     #       --word-slice->end to skip ':'
12775     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
12776     #       append-to-block(out-addr, named-block)
12777     #     else if slice-equal?(word-slice, "var")
12778     #       var-def = parse-mu-var-def(line, vars, fn)
12779     #       append-to-block(out-addr, var-def)
12780     #     else
12781     #       stmt = parse-mu-stmt(line, vars, fn)
12782     #       append-to-block(out-addr, stmt)
12783     #   pop(vars)
12784     #
12785     # . prologue
12786     55/push-ebp
12787     89/<- %ebp 4/r32/esp
12788     # . save registers
12789     50/push-eax
12790     51/push-ecx
12791     52/push-edx
12792     53/push-ebx
12793     57/push-edi
12794     # var line/ecx: (stream byte 512)
12795     81 5/subop/subtract %esp 0x200/imm32
12796     68/push 0x200/imm32/size
12797     68/push 0/imm32/read
12798     68/push 0/imm32/write
12799     89/<- %ecx 4/r32/esp
12800     # var word-slice/edx: slice
12801     68/push 0/imm32/end
12802     68/push 0/imm32/start
12803     89/<- %edx 4/r32/esp
12804     # allocate into out
12805     (allocate Heap *Stmt-size *(ebp+0x14))
12806     # var out-addr/edi: (addr block) = lookup(*out)
12807     8b/-> *(ebp+0x14) 7/r32/edi
12808     (lookup *edi *(edi+4))  # => eax
12809     89/<- %edi 0/r32/eax
12810     # out-addr->tag is 0 (block) by default
12811     # set out-addr->var
12812     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
12813     (new-block-name *(ebp+0x10) %eax)
12814     # push(vars, out-addr->var)
12815     (push *(ebp+0xc) *(edi+0xc))  # Block-var
12816     (push *(ebp+0xc) *(edi+0x10))  # Block-var
12817     (push *(ebp+0xc) 0)  # false
12818     # increment *Curr-block-depth
12819     ff 0/subop/increment *Curr-block-depth
12820     {
12821 $parse-mu-block:line-loop:
12822       # line = read-line-buffered(in)
12823       (clear-stream %ecx)
12824       (read-line-buffered *(ebp+8) %ecx)
12825 #?       (write-buffered Stderr "line: ")
12826 #?       (write-stream-data Stderr %ecx)
12827 #? #?       (write-buffered Stderr Newline)  # line has its own newline
12828 #?       (flush Stderr)
12829 #?       (rewind-stream %ecx)
12830       # if (line->write == 0) break
12831       81 7/subop/compare *ecx 0/imm32
12832       0f 84/jump-if-= break/disp32
12833 #?       (write-buffered Stderr "vars:\n")
12834 #?       (dump-vars *(ebp+0xc))
12835       # word-slice = next-mu-token(line)
12836       (next-mu-token %ecx %edx)
12837 #?       (write-buffered Stderr "word: ")
12838 #?       (write-slice-buffered Stderr %edx)
12839 #?       (write-buffered Stderr Newline)
12840 #?       (flush Stderr)
12841       # if slice-empty?(word-slice) continue
12842       (slice-empty? %edx)
12843       3d/compare-eax-and 0/imm32/false
12844       0f 85/jump-if-!= loop/disp32
12845       # if (slice-starts-with?(word-slice, '#') continue
12846       # . eax = *word-slice->start
12847       8b/-> *edx 0/r32/eax
12848       8a/copy-byte *eax 0/r32/AL
12849       81 4/subop/and %eax 0xff/imm32
12850       # . if (eax == '#') continue
12851       3d/compare-eax-and 0x23/imm32/hash
12852       0f 84/jump-if-= loop/disp32
12853       # if slice-equal?(word-slice, "{")
12854       {
12855 $parse-mu-block:check-for-block:
12856         (slice-equal? %edx "{")
12857         3d/compare-eax-and 0/imm32/false
12858         74/jump-if-= break/disp8
12859         (check-no-tokens-left %ecx)
12860         # parse new block and append
12861         # . var tmp/eax: (handle block)
12862         68/push 0/imm32
12863         68/push 0/imm32
12864         89/<- %eax 4/r32/esp
12865         # .
12866         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
12867         (append-to-block Heap %edi  *eax *(eax+4))
12868         # . reclaim tmp
12869         81 0/subop/add %esp 8/imm32
12870         # .
12871         e9/jump $parse-mu-block:line-loop/disp32
12872       }
12873       # if slice-equal?(word-slice, "}") break
12874 $parse-mu-block:check-for-end:
12875       (slice-equal? %edx "}")
12876       3d/compare-eax-and 0/imm32/false
12877       0f 85/jump-if-!= break/disp32
12878       # if slice-ends-with?(word-slice, ":") parse named block and append
12879       {
12880 $parse-mu-block:check-for-named-block:
12881         # . eax = *(word-slice->end-1)
12882         8b/-> *(edx+4) 0/r32/eax
12883         48/decrement-eax
12884         8a/copy-byte *eax 0/r32/AL
12885         81 4/subop/and %eax 0xff/imm32
12886         # . if (eax != ':') break
12887         3d/compare-eax-and 0x3a/imm32/colon
12888         0f 85/jump-if-!= break/disp32
12889         # TODO: error-check the rest of 'line'
12890         #
12891         # skip ':'
12892         ff 1/subop/decrement *(edx+4)  # Slice-end
12893         # var tmp/eax: (handle block)
12894         68/push 0/imm32
12895         68/push 0/imm32
12896         89/<- %eax 4/r32/esp
12897         #
12898         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
12899         (append-to-block Heap %edi  *eax *(eax+4))
12900         # reclaim tmp
12901         81 0/subop/add %esp 8/imm32
12902         #
12903         e9/jump $parse-mu-block:line-loop/disp32
12904       }
12905       # if slice-equal?(word-slice, "var")
12906       {
12907 $parse-mu-block:check-for-var:
12908         (slice-equal? %edx "var")
12909         3d/compare-eax-and 0/imm32/false
12910         74/jump-if-= break/disp8
12911         # var tmp/eax: (handle block)
12912         68/push 0/imm32
12913         68/push 0/imm32
12914         89/<- %eax 4/r32/esp
12915         #
12916         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
12917         (append-to-block Heap %edi  *eax *(eax+4))
12918         # reclaim tmp
12919         81 0/subop/add %esp 8/imm32
12920         #
12921         e9/jump $parse-mu-block:line-loop/disp32
12922       }
12923 $parse-mu-block:regular-stmt:
12924       # otherwise
12925       # var tmp/eax: (handle block)
12926       68/push 0/imm32
12927       68/push 0/imm32
12928       89/<- %eax 4/r32/esp
12929       #
12930       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
12931       (append-to-block Heap %edi  *eax *(eax+4))
12932       # reclaim tmp
12933       81 0/subop/add %esp 8/imm32
12934       #
12935       e9/jump loop/disp32
12936     } # end line loop
12937     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
12938     # decrement *Curr-block-depth
12939     ff 1/subop/decrement *Curr-block-depth
12940     # pop(vars)
12941     (pop *(ebp+0xc))  # => eax
12942     (pop *(ebp+0xc))  # => eax
12943     (pop *(ebp+0xc))  # => eax
12944 $parse-mu-block:end:
12945     # . reclaim locals
12946     81 0/subop/add %esp 0x214/imm32
12947     # . restore registers
12948     5f/pop-to-edi
12949     5b/pop-to-ebx
12950     5a/pop-to-edx
12951     59/pop-to-ecx
12952     58/pop-to-eax
12953     # . epilogue
12954     89/<- %esp 5/r32/ebp
12955     5d/pop-to-ebp
12956     c3/return
12957 
12958 $parse-mu-block:abort:
12959     # error("'{' or '}' should be on its own line, but got '")
12960     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
12961     (rewind-stream %ecx)
12962     (write-stream-data *(ebp+0x18) %ecx)
12963     (write-buffered *(ebp+0x18) "'\n")
12964     (flush *(ebp+0x18))
12965     (stop *(ebp+0x1c) 1)
12966     # never gets here
12967 
12968 new-block-name:  # fn: (addr function), out: (addr handle var)
12969     # . prologue
12970     55/push-ebp
12971     89/<- %ebp 4/r32/esp
12972     # . save registers
12973     50/push-eax
12974     51/push-ecx
12975     52/push-edx
12976     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
12977     8b/-> *(ebp+8) 0/r32/eax
12978     (lookup *eax *(eax+4))  # Function-name Function-name => eax
12979     8b/-> *eax 0/r32/eax  # String-size
12980     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
12981     89/<- %ecx 0/r32/eax
12982     # var name/edx: (stream byte n)
12983     29/subtract-from %esp 1/r32/ecx
12984     ff 6/subop/push %ecx
12985     68/push 0/imm32/read
12986     68/push 0/imm32/write
12987     89/<- %edx 4/r32/esp
12988     (clear-stream %edx)
12989     # eax = fn->name
12990     8b/-> *(ebp+8) 0/r32/eax
12991     (lookup *eax *(eax+4))  # Function-name Function-name => eax
12992     # construct result using Next-block-index (and increment it)
12993     (write %edx "$")
12994     (write %edx %eax)
12995     (write %edx ":")
12996     (write-int32-hex %edx *Next-block-index)
12997     ff 0/subop/increment *Next-block-index
12998     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
12999     # . eax = name->write
13000     8b/-> *edx 0/r32/eax
13001     # . edx = name->data
13002     8d/copy-address *(edx+0xc) 2/r32/edx
13003     # . eax = name->write + name->data
13004     01/add-to %eax 2/r32/edx
13005     # . push {edx, eax}
13006     ff 6/subop/push %eax
13007     ff 6/subop/push %edx
13008     89/<- %eax 4/r32/esp
13009     # out = new literal(s)
13010     (new-literal Heap %eax *(ebp+0xc))
13011 #?     8b/-> *(ebp+0xc) 0/r32/eax
13012 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
13013 #?     (write-int32-hex-buffered Stderr *(eax+8))
13014 #?     (write-buffered Stderr " for var ")
13015 #?     (write-int32-hex-buffered Stderr %eax)
13016 #?     (write-buffered Stderr Newline)
13017 #?     (flush Stderr)
13018 $new-block-name:end:
13019     # . reclaim locals
13020     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
13021     81 0/subop/add %ecx 8/imm32  # slice
13022     01/add-to %esp 1/r32/ecx
13023     # . restore registers
13024     5a/pop-to-edx
13025     59/pop-to-ecx
13026     58/pop-to-eax
13027     # . epilogue
13028     89/<- %esp 5/r32/ebp
13029     5d/pop-to-ebp
13030     c3/return
13031 
13032 check-no-tokens-left:  # line: (addr stream byte)
13033     # . prologue
13034     55/push-ebp
13035     89/<- %ebp 4/r32/esp
13036     # . save registers
13037     50/push-eax
13038     51/push-ecx
13039     # var s/ecx: slice
13040     68/push 0/imm32/end
13041     68/push 0/imm32/start
13042     89/<- %ecx 4/r32/esp
13043     #
13044     (next-mu-token *(ebp+8) %ecx)
13045     # if slice-empty?(s) return
13046     (slice-empty? %ecx)
13047     3d/compare-eax-and 0/imm32/false
13048     75/jump-if-!= $check-no-tokens-left:end/disp8
13049     # if (slice-starts-with?(s, '#') return
13050     # . eax = *s->start
13051     8b/-> *edx 0/r32/eax
13052     8a/copy-byte *eax 0/r32/AL
13053     81 4/subop/and %eax 0xff/imm32
13054     # . if (eax == '#') continue
13055     3d/compare-eax-and 0x23/imm32/hash
13056     74/jump-if-= $check-no-tokens-left:end/disp8
13057     # abort
13058     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
13059     (rewind-stream %ecx)
13060     (write-stream 2 %ecx)
13061     (write-buffered Stderr "'\n")
13062     (flush Stderr)
13063     # . syscall(exit, 1)
13064     bb/copy-to-ebx  1/imm32
13065     e8/call syscall_exit/disp32
13066     # never gets here
13067 $check-no-tokens-left:end:
13068     # . reclaim locals
13069     81 0/subop/add %esp 8/imm32
13070     # . restore registers
13071     59/pop-to-ecx
13072     58/pop-to-eax
13073     # . epilogue
13074     89/<- %esp 5/r32/ebp
13075     5d/pop-to-ebp
13076     c3/return
13077 
13078 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)
13079     # pseudocode:
13080     #   var v: (handle var)
13081     #   new-literal(name, v)
13082     #   push(vars, {v, false})
13083     #   parse-mu-block(in, vars, fn, out)
13084     #   pop(vars)
13085     #   out->tag = block
13086     #   out->var = v
13087     #
13088     # . prologue
13089     55/push-ebp
13090     89/<- %ebp 4/r32/esp
13091     # . save registers
13092     50/push-eax
13093     51/push-ecx
13094     57/push-edi
13095     # var v/ecx: (handle var)
13096     68/push 0/imm32
13097     68/push 0/imm32
13098     89/<- %ecx 4/r32/esp
13099     #
13100     (new-literal Heap *(ebp+8) %ecx)
13101     # push(vars, v)
13102     (push *(ebp+0x10) *ecx)
13103     (push *(ebp+0x10) *(ecx+4))
13104     (push *(ebp+0x10) 0)  # false
13105     #
13106     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
13107     # pop v off vars
13108     (pop *(ebp+0x10))  # => eax
13109     (pop *(ebp+0x10))  # => eax
13110     (pop *(ebp+0x10))  # => eax
13111     # var out-addr/edi: (addr stmt) = lookup(*out)
13112     8b/-> *(ebp+0x18) 7/r32/edi
13113     (lookup *edi *(edi+4))  # => eax
13114     89/<- %edi 0/r32/eax
13115     # out-addr->tag = named-block
13116     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
13117     # out-addr->var = v
13118     8b/-> *ecx 0/r32/eax
13119     89/<- *(edi+0xc) 0/r32/eax  # Block-var
13120     8b/-> *(ecx+4) 0/r32/eax
13121     89/<- *(edi+0x10) 0/r32/eax  # Block-var
13122 $parse-mu-named-block:end:
13123     # . reclaim locals
13124     81 0/subop/add %esp 8/imm32
13125     # . restore registers
13126     5f/pop-to-edi
13127     59/pop-to-ecx
13128     58/pop-to-eax
13129     # . epilogue
13130     89/<- %esp 5/r32/ebp
13131     5d/pop-to-ebp
13132     c3/return
13133 
13134 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)
13135     # . prologue
13136     55/push-ebp
13137     89/<- %ebp 4/r32/esp
13138     # . save registers
13139     50/push-eax
13140     51/push-ecx
13141     52/push-edx
13142     53/push-ebx
13143     57/push-edi
13144     # edi = out
13145     8b/-> *(ebp+0x10) 7/r32/edi
13146     # var word-slice/ecx: slice
13147     68/push 0/imm32/end
13148     68/push 0/imm32/start
13149     89/<- %ecx 4/r32/esp
13150     # var v/edx: (handle var)
13151     68/push 0/imm32
13152     68/push 0/imm32
13153     89/<- %edx 4/r32/esp
13154     # v = parse-var-with-type(next-mu-token(line))
13155     (next-mu-token *(ebp+8) %ecx)
13156     (parse-var-with-type %ecx *(ebp+8) %edx *(ebp+0x18) *(ebp+0x1c))
13157     # var v-addr/eax: (addr var)
13158     (lookup *edx *(edx+4))  # => eax
13159     # v->block-depth = *Curr-block-depth
13160     8b/-> *Curr-block-depth 3/r32/ebx
13161     89/<- *(eax+0x10) 3/r32/ebx  # Var-block-depth
13162     # either v has no register and there's no more to this line
13163     8b/-> *(eax+0x18) 0/r32/eax  # Var-register
13164     3d/compare-eax-and 0/imm32
13165     {
13166       75/jump-if-!= break/disp8
13167       # TODO: disallow vars of type 'byte' on the stack
13168       # ensure that there's nothing else on this line
13169       (next-mu-token *(ebp+8) %ecx)
13170       (slice-empty? %ecx)  # => eax
13171       3d/compare-eax-and 0/imm32/false
13172       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
13173       #
13174       (new-var-def Heap  *edx *(edx+4)  %edi)
13175       e9/jump $parse-mu-var-def:update-vars/disp32
13176     }
13177     # or v has a register and there's more to this line
13178     {
13179       0f 84/jump-if-= break/disp32
13180       # TODO: disallow vars of type 'byte' in registers 'esi' or 'edi'
13181       # TODO: vars of type 'byte' should only be initialized by clearing to 0
13182       # ensure that the next word is '<-'
13183       (next-mu-token *(ebp+8) %ecx)
13184       (slice-equal? %ecx "<-")  # => eax
13185       3d/compare-eax-and 0/imm32/false
13186       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
13187       #
13188       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
13189       (lookup *edi *(edi+4))  # => eax
13190       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13191     }
13192 $parse-mu-var-def:update-vars:
13193     # push 'v' at end of function
13194     (push *(ebp+0xc) *edx)
13195     (push *(ebp+0xc) *(edx+4))
13196     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
13197 $parse-mu-var-def:end:
13198     # . reclaim locals
13199     81 0/subop/add %esp 0x10/imm32
13200     # . restore registers
13201     5f/pop-to-edi
13202     5b/pop-to-ebx
13203     5a/pop-to-edx
13204     59/pop-to-ecx
13205     58/pop-to-eax
13206     # . epilogue
13207     89/<- %esp 5/r32/ebp
13208     5d/pop-to-ebp
13209     c3/return
13210 
13211 $parse-mu-var-def:error1:
13212     (rewind-stream *(ebp+8))
13213     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
13214     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
13215     (flush *(ebp+0x18))
13216     (write-stream-data *(ebp+0x18) *(ebp+8))
13217     (write-buffered *(ebp+0x18) "'\n")
13218     (flush *(ebp+0x18))
13219     (stop *(ebp+0x1c) 1)
13220     # never gets here
13221 
13222 $parse-mu-var-def:error2:
13223     (rewind-stream *(ebp+8))
13224     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
13225     (write-buffered *(ebp+0x18) "fn ")
13226     8b/-> *(ebp+0x14) 0/r32/eax
13227     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13228     (write-buffered *(ebp+0x18) %eax)
13229     (write-buffered *(ebp+0x18) ": var ")
13230     # var v-addr/eax: (addr var) = lookup(v)
13231     (lookup *edx *(edx+4))  # => eax
13232     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13233     (write-buffered *(ebp+0x18) %eax)
13234     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
13235     (flush *(ebp+0x18))
13236     (stop *(ebp+0x1c) 1)
13237     # never gets here
13238 
13239 test-parse-mu-var-def:
13240     # 'var n: int'
13241     # . prologue
13242     55/push-ebp
13243     89/<- %ebp 4/r32/esp
13244     # setup
13245     8b/-> *Primitive-type-ids 0/r32/eax
13246     89/<- *Type-id 0/r32/eax  # stream-write
13247     (clear-stream _test-input-stream)
13248     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
13249     c7 0/subop/copy *Curr-block-depth 1/imm32
13250     # var out/esi: (handle stmt)
13251     68/push 0/imm32
13252     68/push 0/imm32
13253     89/<- %esi 4/r32/esp
13254     # var vars/ecx: (stack (addr var) 16)
13255     81 5/subop/subtract %esp 0xc0/imm32
13256     68/push 0xc0/imm32/size
13257     68/push 0/imm32/top
13258     89/<- %ecx 4/r32/esp
13259     (clear-stack %ecx)
13260     # convert
13261     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
13262     # var out-addr/esi: (addr stmt)
13263     (lookup *esi *(esi+4))  # => eax
13264     89/<- %esi 0/r32/eax
13265     #
13266     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
13267     # var v/ecx: (addr var) = lookup(out->var)
13268     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
13269     89/<- %ecx 0/r32/eax
13270     # v->name
13271     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
13272     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
13273     # v->register
13274     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
13275     # v->block-depth
13276     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
13277     # v->type == int
13278     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
13279     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
13280     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
13281     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
13282     # . epilogue
13283     89/<- %esp 5/r32/ebp
13284     5d/pop-to-ebp
13285     c3/return
13286 
13287 test-parse-mu-reg-var-def:
13288     # 'var n/eax: int <- copy 0'
13289     # . prologue
13290     55/push-ebp
13291     89/<- %ebp 4/r32/esp
13292     # setup
13293     8b/-> *Primitive-type-ids 0/r32/eax
13294     89/<- *Type-id 0/r32/eax  # stream-write
13295     (clear-stream _test-input-stream)
13296     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
13297     c7 0/subop/copy *Curr-block-depth 1/imm32
13298     # var out/esi: (handle stmt)
13299     68/push 0/imm32
13300     68/push 0/imm32
13301     89/<- %esi 4/r32/esp
13302     # var vars/ecx: (stack (addr var) 16)
13303     81 5/subop/subtract %esp 0xc0/imm32
13304     68/push 0xc0/imm32/size
13305     68/push 0/imm32/top
13306     89/<- %ecx 4/r32/esp
13307     (clear-stack %ecx)
13308     # convert
13309     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
13310     # var out-addr/esi: (addr stmt)
13311     (lookup *esi *(esi+4))  # => eax
13312     89/<- %esi 0/r32/eax
13313     #
13314     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
13315     # var v/ecx: (addr var) = lookup(out->outputs->value)
13316     # . eax: (addr stmt-var) = lookup(out->outputs)
13317     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
13318     # .
13319     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
13320     # . eax: (addr var) = lookup(eax->value)
13321     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13322     # . ecx = eax
13323     89/<- %ecx 0/r32/eax
13324     # v->name
13325     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
13326     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
13327     # v->register
13328     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
13329     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
13330     # v->block-depth
13331     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
13332     # v->type == int
13333     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
13334     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
13335     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
13336     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
13337     # . epilogue
13338     89/<- %esp 5/r32/ebp
13339     5d/pop-to-ebp
13340     c3/return
13341 
13342 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)
13343     # pseudocode:
13344     #   var name: slice
13345     #   allocate(Heap, Stmt-size, out)
13346     #   var out-addr: (addr stmt) = lookup(*out)
13347     #   out-addr->tag = stmt
13348     #   if stmt-has-outputs?(line)
13349     #     while true
13350     #       name = next-mu-token(line)
13351     #       if (name == '<-') break
13352     #       assert(is-identifier?(name))
13353     #       var v: (handle var) = lookup-var(name, vars)
13354     #       out-addr->outputs = append(v, out-addr->outputs)
13355     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
13356     #
13357     # . prologue
13358     55/push-ebp
13359     89/<- %ebp 4/r32/esp
13360     # . save registers
13361     50/push-eax
13362     51/push-ecx
13363     52/push-edx
13364     53/push-ebx
13365     57/push-edi
13366     # var name/ecx: slice
13367     68/push 0/imm32/end
13368     68/push 0/imm32/start
13369     89/<- %ecx 4/r32/esp
13370     # var is-deref?/edx: boolean = false
13371     ba/copy-to-edx 0/imm32/false
13372     # var v: (handle var)
13373     68/push 0/imm32
13374     68/push 0/imm32
13375     89/<- %ebx 4/r32/esp
13376     #
13377     (allocate Heap *Stmt-size *(ebp+0x14))
13378     # var out-addr/edi: (addr stmt) = lookup(*out)
13379     8b/-> *(ebp+0x14) 7/r32/edi
13380     (lookup *edi *(edi+4))  # => eax
13381     89/<- %edi 0/r32/eax
13382     # out-addr->tag = 1/stmt
13383     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
13384     {
13385       (stmt-has-outputs? *(ebp+8))
13386       3d/compare-eax-and 0/imm32/false
13387       0f 84/jump-if-= break/disp32
13388       {
13389 $parse-mu-stmt:read-outputs:
13390         # name = next-mu-token(line)
13391         (next-mu-token *(ebp+8) %ecx)
13392         # if slice-empty?(word-slice) break
13393         (slice-empty? %ecx)  # => eax
13394         3d/compare-eax-and 0/imm32/false
13395         0f 85/jump-if-!= break/disp32
13396         # if (name == "<-") break
13397         (slice-equal? %ecx "<-")  # => eax
13398         3d/compare-eax-and 0/imm32/false
13399         0f 85/jump-if-!= break/disp32
13400         # is-deref? = false
13401         ba/copy-to-edx 0/imm32/false
13402         # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
13403         8b/-> *ecx 0/r32/eax  # Slice-start
13404         8a/copy-byte *eax 0/r32/AL
13405         81 4/subop/and %eax 0xff/imm32
13406         3d/compare-eax-and 0x2a/imm32/asterisk
13407         {
13408           75/jump-if-!= break/disp8
13409           ff 0/subop/increment *ecx
13410           ba/copy-to-edx 1/imm32/true
13411         }
13412         # assert(is-identifier?(name))
13413         (is-identifier? %ecx)  # => eax
13414         3d/compare-eax-and 0/imm32/false
13415         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
13416         #
13417         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
13418         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
13419         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  %edx  %eax)  # Stmt1-outputs
13420         #
13421         e9/jump loop/disp32
13422       }
13423     }
13424     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
13425 $parse-mu-stmt:end:
13426     # . reclaim locals
13427     81 0/subop/add %esp 0x10/imm32
13428     # . restore registers
13429     5f/pop-to-edi
13430     5b/pop-to-ebx
13431     5a/pop-to-edx
13432     59/pop-to-ecx
13433     58/pop-to-eax
13434     # . epilogue
13435     89/<- %esp 5/r32/ebp
13436     5d/pop-to-ebp
13437     c3/return
13438 
13439 $parse-mu-stmt:abort:
13440     # error("invalid identifier '" name "'\n")
13441     (write-buffered *(ebp+0x18) "invalid identifier '")
13442     (write-slice-buffered *(ebp+0x18) %ecx)
13443     (write-buffered *(ebp+0x18) "'\n")
13444     (flush *(ebp+0x18))
13445     (stop *(ebp+0x1c) 1)
13446     # never gets here
13447 
13448 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)
13449     # pseudocode:
13450     #   stmt->name = slice-to-string(next-mu-token(line))
13451     #   while true
13452     #     name = next-mu-token(line)
13453     #     v = lookup-var-or-literal(name)
13454     #     stmt->inouts = append(v, stmt->inouts)
13455     #
13456     # . prologue
13457     55/push-ebp
13458     89/<- %ebp 4/r32/esp
13459     # . save registers
13460     50/push-eax
13461     51/push-ecx
13462     52/push-edx
13463     53/push-ebx
13464     56/push-esi
13465     57/push-edi
13466     # edi = stmt
13467     8b/-> *(ebp+8) 7/r32/edi
13468     # var name/ecx: slice
13469     68/push 0/imm32/end
13470     68/push 0/imm32/start
13471     89/<- %ecx 4/r32/esp
13472     # var is-deref?/edx: boolean = false
13473     ba/copy-to-edx 0/imm32/false
13474     # var v/esi: (handle var)
13475     68/push 0/imm32
13476     68/push 0/imm32
13477     89/<- %esi 4/r32/esp
13478 $add-operation-and-inputs-to-stmt:read-operation:
13479     (next-mu-token *(ebp+0xc) %ecx)
13480     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
13481     (slice-to-string Heap %ecx %eax)
13482     # var is-get?/ebx: boolean = (name == "get")
13483     (slice-equal? %ecx "get")  # => eax
13484     89/<- %ebx 0/r32/eax
13485     {
13486 $add-operation-and-inputs-to-stmt:read-inouts:
13487       # name = next-mu-token(line)
13488       (next-mu-token *(ebp+0xc) %ecx)
13489       # if slice-empty?(word-slice) break
13490       (slice-empty? %ecx)  # => eax
13491       3d/compare-eax-and 0/imm32/false
13492       0f 85/jump-if-!= break/disp32
13493       # if (name == "<-") abort
13494       (slice-equal? %ecx "<-")
13495       3d/compare-eax-and 0/imm32/false
13496       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
13497       # if (is-get? && second operand) lookup or create offset
13498       {
13499         81 7/subop/compare %ebx 0/imm32/false
13500         74/jump-if-= break/disp8
13501         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13502         3d/compare-eax-and 0/imm32
13503         74/jump-if-= break/disp8
13504         (lookup-or-create-constant %eax %ecx %esi)
13505 #?         (lookup *esi *(esi+4))
13506 #?         (write-buffered Stderr "creating new output var ")
13507 #?         (write-int32-hex-buffered Stderr %eax)
13508 #?         (write-buffered Stderr " for field called ")
13509 #?         (write-slice-buffered Stderr %ecx)
13510 #?         (write-buffered Stderr "; var name ")
13511 #?         (lookup *eax *(eax+4))  # Var-name
13512 #?         (write-buffered Stderr %eax)
13513 #?         (write-buffered Stderr Newline)
13514 #?         (flush Stderr)
13515         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
13516       }
13517       # is-deref? = false
13518       ba/copy-to-edx 0/imm32/false
13519       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
13520       8b/-> *ecx 0/r32/eax  # Slice-start
13521       8a/copy-byte *eax 0/r32/AL
13522       81 4/subop/and %eax 0xff/imm32
13523       3d/compare-eax-and 0x2a/imm32/asterisk
13524       {
13525         75/jump-if-!= break/disp8
13526 $add-operation-and-inputs-to-stmt:inout-is-deref:
13527         ff 0/subop/increment *ecx
13528         ba/copy-to-edx 1/imm32/true
13529       }
13530       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13531 $add-operation-and-inputs-to-stmt:save-var:
13532       8d/copy-address *(edi+0xc) 0/r32/eax
13533       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
13534       #
13535       e9/jump loop/disp32
13536     }
13537 $add-operation-and-inputs-to-stmt:end:
13538     # . reclaim locals
13539     81 0/subop/add %esp 0x10/imm32
13540     # . restore registers
13541     5f/pop-to-edi
13542     5e/pop-to-esi
13543     5b/pop-to-ebx
13544     5a/pop-to-edx
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 $add-operation-and-inputs-to-stmt:abort:
13553     # error("fn ___: invalid identifier in '" line "'\n")
13554     (write-buffered *(ebp+0x18) "fn ")
13555     8b/-> *(ebp+0x14) 0/r32/eax
13556     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13557     (write-buffered *(ebp+0x18) %eax)
13558     (rewind-stream *(ebp+0xc))
13559     (write-buffered *(ebp+0x18) ": invalid identifier in '")
13560     (write-stream-data *(ebp+0x18) *(ebp+0xc))
13561     (write-buffered *(ebp+0x18) "'\n")
13562     (flush *(ebp+0x18))
13563     (stop *(ebp+0x1c) 1)
13564     # never gets here
13565 
13566 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
13567     # . prologue
13568     55/push-ebp
13569     89/<- %ebp 4/r32/esp
13570     # . save registers
13571     51/push-ecx
13572     # var word-slice/ecx: slice
13573     68/push 0/imm32/end
13574     68/push 0/imm32/start
13575     89/<- %ecx 4/r32/esp
13576     # result = false
13577     b8/copy-to-eax 0/imm32/false
13578     (rewind-stream *(ebp+8))
13579     {
13580       (next-mu-token *(ebp+8) %ecx)
13581       # if slice-empty?(word-slice) break
13582       (slice-empty? %ecx)
13583       3d/compare-eax-and 0/imm32/false
13584       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
13585       0f 85/jump-if-!= break/disp32
13586       # if slice-starts-with?(word-slice, '#') break
13587       # . eax = *word-slice->start
13588       8b/-> *ecx 0/r32/eax
13589       8a/copy-byte *eax 0/r32/AL
13590       81 4/subop/and %eax 0xff/imm32
13591       # . if (eax == '#') break
13592       3d/compare-eax-and 0x23/imm32/hash
13593       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
13594       0f 84/jump-if-= break/disp32
13595       # if slice-equal?(word-slice, '<-') return true
13596       (slice-equal? %ecx "<-")
13597       3d/compare-eax-and 0/imm32/false
13598       74/jump-if-= loop/disp8
13599       b8/copy-to-eax 1/imm32/true
13600     }
13601 $stmt-has-outputs:end:
13602     (rewind-stream *(ebp+8))
13603     # . reclaim locals
13604     81 0/subop/add %esp 8/imm32
13605     # . restore registers
13606     59/pop-to-ecx
13607     # . epilogue
13608     89/<- %esp 5/r32/ebp
13609     5d/pop-to-ebp
13610     c3/return
13611 
13612 # if 'name' starts with a digit, create a new literal var for it
13613 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
13614 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)
13615     # . prologue
13616     55/push-ebp
13617     89/<- %ebp 4/r32/esp
13618     # . save registers
13619     50/push-eax
13620     51/push-ecx
13621     56/push-esi
13622     # esi = name
13623     8b/-> *(ebp+8) 6/r32/esi
13624     # if slice-empty?(name) abort
13625     (slice-empty? %esi)  # => eax
13626     3d/compare-eax-and 0/imm32/false
13627     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
13628     # var c/ecx: byte = *name->start
13629     8b/-> *esi 1/r32/ecx
13630     8a/copy-byte *ecx 1/r32/CL
13631     81 4/subop/and %ecx 0xff/imm32
13632     # if (is-decimal-digit?(c) || c == '-') return new var(name)
13633     {
13634       81 7/subop/compare %ecx 0x2d/imm32/dash
13635       74/jump-if-= $lookup-var-or-literal:literal/disp8
13636       (is-decimal-digit? %ecx)  # => eax
13637       3d/compare-eax-and 0/imm32/false
13638       74/jump-if-= break/disp8
13639 $lookup-var-or-literal:literal:
13640       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13641       eb/jump $lookup-var-or-literal:end/disp8
13642     }
13643     # else if (c == '"') return new var(name)
13644     {
13645       81 7/subop/compare %ecx 0x22/imm32/dquote
13646       75/jump-if-!= break/disp8
13647 $lookup-var-or-literal:literal-string:
13648       (new-literal Heap %esi *(ebp+0x10))
13649       eb/jump $lookup-var-or-literal:end/disp8
13650     }
13651     # otherwise return lookup-var(name, vars)
13652     {
13653 $lookup-var-or-literal:var:
13654       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13655     }
13656 $lookup-var-or-literal:end:
13657     # . restore registers
13658     5e/pop-to-esi
13659     59/pop-to-ecx
13660     58/pop-to-eax
13661     # . epilogue
13662     89/<- %esp 5/r32/ebp
13663     5d/pop-to-ebp
13664     c3/return
13665 
13666 $lookup-var-or-literal:abort:
13667     (write-buffered *(ebp+0x18) "fn ")
13668     8b/-> *(ebp+0x14) 0/r32/eax
13669     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13670     (write-buffered *(ebp+0x18) %eax)
13671     (write-buffered *(ebp+0x18) ": empty variable!")
13672     (flush *(ebp+0x18))
13673     (stop *(ebp+0x1c) 1)
13674     # never gets here
13675 
13676 # return first 'name' from the top (back) of 'vars' and abort if not found
13677 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)
13678     # . prologue
13679     55/push-ebp
13680     89/<- %ebp 4/r32/esp
13681     # . save registers
13682     50/push-eax
13683     #
13684     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13685     # if (*out == 0) abort
13686     8b/-> *(ebp+0x10) 0/r32/eax
13687     81 7/subop/compare *eax 0/imm32
13688     74/jump-if-= $lookup-var:abort/disp8
13689 $lookup-var:end:
13690     # . restore registers
13691     58/pop-to-eax
13692     # . epilogue
13693     89/<- %esp 5/r32/ebp
13694     5d/pop-to-ebp
13695     c3/return
13696 
13697 $lookup-var:abort:
13698     (write-buffered *(ebp+0x18) "fn ")
13699     8b/-> *(ebp+0x14) 0/r32/eax
13700     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13701     (write-buffered *(ebp+0x18) %eax)
13702     (write-buffered *(ebp+0x18) ": unknown variable '")
13703     (write-slice-buffered *(ebp+0x18) *(ebp+8))
13704     (write-buffered *(ebp+0x18) "'\n")
13705     (flush *(ebp+0x18))
13706     (stop *(ebp+0x1c) 1)
13707     # never gets here
13708 
13709 # return first 'name' from the top (back) of 'vars', and 0/null if not found
13710 # ensure that 'name' if in a register is the topmost variable in that register
13711 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)
13712     # pseudocode:
13713     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
13714     #   var min = vars->data
13715     #   while curr >= min
13716     #     var v: (handle var) = *curr
13717     #     if v->name == name
13718     #       return
13719     #     curr -= 12
13720     #
13721     # . prologue
13722     55/push-ebp
13723     89/<- %ebp 4/r32/esp
13724     # . save registers
13725     50/push-eax
13726     51/push-ecx
13727     52/push-edx
13728     53/push-ebx
13729     56/push-esi
13730     57/push-edi
13731     # clear out
13732     (zero-out *(ebp+0x10) *Handle-size)
13733     # esi = vars
13734     8b/-> *(ebp+0xc) 6/r32/esi
13735     # ebx = vars->top
13736     8b/-> *esi 3/r32/ebx
13737     # if (vars->top > vars->size) abort
13738     3b/compare<- *(esi+4) 0/r32/eax
13739     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
13740     # var min/edx: (addr handle var) = vars->data
13741     8d/copy-address *(esi+8) 2/r32/edx
13742     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
13743     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
13744     # var var-in-reg/edi: 16 addrs
13745     68/push 0/imm32
13746     68/push 0/imm32
13747     68/push 0/imm32
13748     68/push 0/imm32
13749     68/push 0/imm32
13750     68/push 0/imm32
13751     68/push 0/imm32
13752     68/push 0/imm32
13753     68/push 0/imm32
13754     68/push 0/imm32
13755     68/push 0/imm32
13756     68/push 0/imm32
13757     68/push 0/imm32
13758     68/push 0/imm32
13759     68/push 0/imm32
13760     68/push 0/imm32
13761     89/<- %edi 4/r32/esp
13762     {
13763 $lookup-var-helper:loop:
13764       # if (curr < min) return
13765       39/compare %ebx 2/r32/edx
13766       0f 82/jump-if-addr< break/disp32
13767       # var v/ecx: (addr var) = lookup(*curr)
13768       (lookup *ebx *(ebx+4))  # => eax
13769       89/<- %ecx 0/r32/eax
13770       # var vn/eax: (addr array byte) = lookup(v->name)
13771       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
13772       # if (vn == name) return curr
13773       (slice-equal? *(ebp+8) %eax)  # => eax
13774       3d/compare-eax-and 0/imm32/false
13775       {
13776         74/jump-if-= break/disp8
13777 $lookup-var-helper:found:
13778         # var vr/eax: (addr array byte) = lookup(v->register)
13779         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
13780         3d/compare-eax-and 0/imm32
13781         {
13782           74/jump-if-= break/disp8
13783 $lookup-var-helper:found-register:
13784           # var reg/eax: int = get(Registers, vr)
13785           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
13786           8b/-> *eax 0/r32/eax
13787           # if (var-in-reg[reg]) error
13788           8b/-> *(edi+eax<<2) 0/r32/eax
13789           3d/compare-eax-and 0/imm32
13790           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
13791         }
13792 $lookup-var-helper:return:
13793         # esi = out
13794         8b/-> *(ebp+0x10) 6/r32/esi
13795         # *out = *curr
13796         8b/-> *ebx 0/r32/eax
13797         89/<- *esi 0/r32/eax
13798         8b/-> *(ebx+4) 0/r32/eax
13799         89/<- *(esi+4) 0/r32/eax
13800         # return
13801         eb/jump $lookup-var-helper:end/disp8
13802       }
13803       # 'name' not yet found; update var-in-reg if v in register
13804       # . var vr/eax: (addr array byte) = lookup(v->register)
13805       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
13806       # . if (vr == 0) continue
13807       3d/compare-eax-and 0/imm32
13808       74/jump-if-= $lookup-var-helper:continue/disp8
13809       # . var reg/eax: int = get(Registers, vr)
13810       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
13811       8b/-> *eax 0/r32/eax
13812       # . var-in-reg[reg] = v
13813       89/<- *(edi+eax<<2) 1/r32/ecx
13814 $lookup-var-helper:continue:
13815       # curr -= 12
13816       81 5/subop/subtract %ebx 0xc/imm32
13817       e9/jump loop/disp32
13818     }
13819 $lookup-var-helper:end:
13820     # . reclaim locals
13821     81 0/subop/add %esp 0x40/imm32
13822     # . restore registers
13823     5f/pop-to-edi
13824     5e/pop-to-esi
13825     5b/pop-to-ebx
13826     5a/pop-to-edx
13827     59/pop-to-ecx
13828     58/pop-to-eax
13829     # . epilogue
13830     89/<- %esp 5/r32/ebp
13831     5d/pop-to-ebp
13832     c3/return
13833 
13834 $lookup-var-helper:error1:
13835     (write-buffered *(ebp+0x18) "fn ")
13836     8b/-> *(ebp+0x14) 0/r32/eax
13837     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13838     (write-buffered *(ebp+0x18) %eax)
13839     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
13840     (write-slice-buffered *(ebp+0x18) *(ebp+8))
13841     (write-buffered *(ebp+0x18) "'\n")
13842     (flush *(ebp+0x18))
13843     (stop *(ebp+0x1c) 1)
13844     # never gets here
13845 
13846 $lookup-var-helper:error2:
13847     # eax contains the conflicting var at this point
13848     (write-buffered *(ebp+0x18) "fn ")
13849     50/push-eax
13850     8b/-> *(ebp+0x14) 0/r32/eax
13851     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13852     (write-buffered *(ebp+0x18) %eax)
13853     58/pop-eax
13854     (write-buffered *(ebp+0x18) ": register ")
13855     50/push-eax
13856     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
13857     (write-buffered *(ebp+0x18) %eax)
13858     58/pop-to-eax
13859     (write-buffered *(ebp+0x18) " reads var '")
13860     (write-slice-buffered *(ebp+0x18) *(ebp+8))
13861     (write-buffered *(ebp+0x18) "' after writing var '")
13862     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13863     (write-buffered *(ebp+0x18) %eax)
13864     (write-buffered *(ebp+0x18) "'\n")
13865     (flush *(ebp+0x18))
13866     (stop *(ebp+0x1c) 1)
13867     # never gets here
13868 
13869 dump-vars:  # vars: (addr stack live-var)
13870     # pseudocode:
13871     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
13872     #   var min = vars->data
13873     #   while curr >= min
13874     #     var v: (handle var) = *curr
13875     #     print v
13876     #     curr -= 12
13877     #
13878     # . prologue
13879     55/push-ebp
13880     89/<- %ebp 4/r32/esp
13881     # . save registers
13882     52/push-edx
13883     53/push-ebx
13884     56/push-esi
13885     # esi = vars
13886     8b/-> *(ebp+8) 6/r32/esi
13887     # ebx = vars->top
13888     8b/-> *esi 3/r32/ebx
13889     # var min/edx: (addr handle var) = vars->data
13890     8d/copy-address *(esi+8) 2/r32/edx
13891     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
13892     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
13893     {
13894 $dump-vars:loop:
13895       # if (curr < min) return
13896       39/compare %ebx 2/r32/edx
13897       0f 82/jump-if-addr< break/disp32
13898       #
13899       (write-buffered Stderr "  var@")
13900       (dump-var 2 %ebx)
13901       # curr -= 12
13902       81 5/subop/subtract %ebx 0xc/imm32
13903       e9/jump loop/disp32
13904     }
13905 $dump-vars:end:
13906     # . restore registers
13907     5e/pop-to-esi
13908     5b/pop-to-ebx
13909     5a/pop-to-edx
13910     # . epilogue
13911     89/<- %esp 5/r32/ebp
13912     5d/pop-to-ebp
13913     c3/return
13914 
13915 == data
13916 # Like Registers, but no esp or ebp
13917 Mu-registers:  # (addr stream {(handle array byte), int})
13918   # a table is a stream
13919   0xa8/imm32/write
13920   0/imm32/read
13921   0xa8/imm32/length
13922   # data
13923   # general-purpose registers
13924   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
13925   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
13926   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
13927   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
13928   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
13929   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
13930   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
13931   # floating-point registers
13932   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
13933   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
13934   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
13935   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
13936   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
13937   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
13938   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
13939   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
13940 
13941 # Like Mu-registers, but with unique codes for integer and floating-point
13942 # registers.
13943 # Don't use this for code-generation, only for checking.
13944 Mu-registers-unique:  # (addr stream {(handle array byte), int})
13945   # a table is a stream
13946   0xa8/imm32/write
13947   0/imm32/read
13948   0xa8/imm32/length
13949   # data
13950   # general-purpose registers
13951   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
13952   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
13953   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
13954   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
13955   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
13956   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
13957   # floating-point registers
13958   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
13959   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
13960   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
13961   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
13962   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
13963   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
13964   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
13965   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
13966 
13967 $Mu-register-eax:
13968   0x11/imm32/alloc-id
13969   3/imm32/size
13970   0x65/e 0x61/a 0x78/x
13971 
13972 $Mu-register-ecx:
13973   0x11/imm32/alloc-id
13974   3/imm32/size
13975   0x65/e 0x63/c 0x78/x
13976 
13977 $Mu-register-edx:
13978   0x11/imm32/alloc-id
13979   3/imm32/size
13980   0x65/e 0x64/d 0x78/x
13981 
13982 $Mu-register-ebx:
13983   0x11/imm32/alloc-id
13984   3/imm32/size
13985   0x65/e 0x62/b 0x78/x
13986 
13987 $Mu-register-esi:
13988   0x11/imm32/alloc-id
13989   3/imm32/size
13990   0x65/e 0x73/s 0x69/i
13991 
13992 $Mu-register-edi:
13993   0x11/imm32/alloc-id
13994   3/imm32/size
13995   0x65/e 0x64/d 0x69/i
13996 
13997 $Mu-register-xmm0:
13998   0x11/imm32/alloc-id:fake:payload
13999   # "xmm0"
14000   0x4/imm32/size
14001   0x78/x 0x6d/m 0x6d/m 0x30/0
14002 
14003 $Mu-register-xmm1:
14004   0x11/imm32/alloc-id:fake:payload
14005   # "xmm1"
14006   0x4/imm32/size
14007   0x78/x 0x6d/m 0x6d/m 0x31/1
14008 
14009 $Mu-register-xmm2:
14010   0x11/imm32/alloc-id:fake:payload
14011   # "xmm2"
14012   0x4/imm32/size
14013   0x78/x 0x6d/m 0x6d/m 0x32/2
14014 
14015 $Mu-register-xmm3:
14016   0x11/imm32/alloc-id:fake:payload
14017   # "xmm3"
14018   0x4/imm32/size
14019   0x78/x 0x6d/m 0x6d/m 0x33/3
14020 
14021 $Mu-register-xmm4:
14022   0x11/imm32/alloc-id:fake:payload
14023   # "xmm4"
14024   0x4/imm32/size
14025   0x78/x 0x6d/m 0x6d/m 0x34/4
14026 
14027 $Mu-register-xmm5:
14028   0x11/imm32/alloc-id:fake:payload
14029   # "xmm5"
14030   0x4/imm32/size
14031   0x78/x 0x6d/m 0x6d/m 0x35/5
14032 
14033 $Mu-register-xmm6:
14034   0x11/imm32/alloc-id:fake:payload
14035   # "xmm6"
14036   0x4/imm32/size
14037   0x78/x 0x6d/m 0x6d/m 0x36/6
14038 
14039 $Mu-register-xmm7:
14040   0x11/imm32/alloc-id:fake:payload
14041   # "xmm7"
14042   0x4/imm32/size
14043   0x78/x 0x6d/m 0x6d/m 0x37/7
14044 
14045 == code
14046 
14047 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
14048 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
14049     # . prologue
14050     55/push-ebp
14051     89/<- %ebp 4/r32/esp
14052     # . save registers
14053     50/push-eax
14054     # var out-addr/eax: (addr var)
14055     (lookup *(ebp+8) *(ebp+0xc))  # => eax
14056     #
14057     (binding-exists? %eax *(ebp+0x10))  # => eax
14058     3d/compare-eax-and 0/imm32/false
14059     75/jump-if-!= $maybe-define-var:end/disp8
14060     # otherwise update vars
14061     (push *(ebp+0x10) *(ebp+8))
14062     (push *(ebp+0x10) *(ebp+0xc))
14063     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
14064 $maybe-define-var:end:
14065     # . restore registers
14066     58/pop-to-eax
14067     # . epilogue
14068     89/<- %esp 5/r32/ebp
14069     5d/pop-to-ebp
14070     c3/return
14071 
14072 # simpler version of lookup-var-helper
14073 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
14074     # pseudocode:
14075     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
14076     #   var min = vars->data
14077     #   while curr >= min
14078     #     var v: (handle var) = *curr
14079     #     if v->name == target->name
14080     #       return true
14081     #     curr -= 12
14082     #   return false
14083     #
14084     # . prologue
14085     55/push-ebp
14086     89/<- %ebp 4/r32/esp
14087     # . save registers
14088     51/push-ecx
14089     52/push-edx
14090     56/push-esi
14091     # var target-name/ecx: (addr array byte) = lookup(target->name)
14092     8b/-> *(ebp+8) 0/r32/eax
14093     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14094     89/<- %ecx 0/r32/eax
14095     # esi = vars
14096     8b/-> *(ebp+0xc) 6/r32/esi
14097     # eax = vars->top
14098     8b/-> *esi 0/r32/eax
14099     # var min/edx: (addr handle var) = vars->data
14100     8d/copy-address *(esi+8) 2/r32/edx
14101     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
14102     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
14103     {
14104 $binding-exists?:loop:
14105       # if (curr < min) return
14106       39/compare %esi 2/r32/edx
14107       0f 82/jump-if-addr< break/disp32
14108       # var v/eax: (addr var) = lookup(*curr)
14109       (lookup *esi *(esi+4))  # => eax
14110       # var vn/eax: (addr array byte) = lookup(v->name)
14111       (lookup *eax *(eax+4))  # Var-name Var-name => eax
14112       # if (vn == target-name) return true
14113       (string-equal? %ecx %eax)  # => eax
14114       3d/compare-eax-and 0/imm32/false
14115       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
14116       # curr -= 12
14117       81 5/subop/subtract %esi 0xc/imm32
14118       e9/jump loop/disp32
14119     }
14120     b8/copy-to-eax 0/imm32/false
14121 $binding-exists?:end:
14122     # . restore registers
14123     5e/pop-to-esi
14124     5a/pop-to-edx
14125     59/pop-to-ecx
14126     # . epilogue
14127     89/<- %esp 5/r32/ebp
14128     5d/pop-to-ebp
14129     c3/return
14130 
14131 test-parse-mu-stmt:
14132     # . prologue
14133     55/push-ebp
14134     89/<- %ebp 4/r32/esp
14135     # setup
14136     8b/-> *Primitive-type-ids 0/r32/eax
14137     89/<- *Type-id 0/r32/eax  # stream-write
14138     (clear-stream _test-input-stream)
14139     (write _test-input-stream "increment n\n")
14140     # var vars/ecx: (stack (addr var) 16)
14141     81 5/subop/subtract %esp 0xc0/imm32
14142     68/push 0xc0/imm32/size
14143     68/push 0/imm32/top
14144     89/<- %ecx 4/r32/esp
14145     (clear-stack %ecx)
14146     # var v/edx: (handle var)
14147     68/push 0/imm32
14148     68/push 0/imm32
14149     89/<- %edx 4/r32/esp
14150     # var s/eax: (handle array byte)
14151     68/push 0/imm32
14152     68/push 0/imm32
14153     89/<- %eax 4/r32/esp
14154     # v = new var("n")
14155     (copy-array Heap "n" %eax)
14156     (new-var Heap *eax *(eax+4) %edx)
14157     #
14158     (push %ecx *edx)
14159     (push %ecx *(edx+4))
14160     (push %ecx 0)
14161     # var out/eax: (handle stmt)
14162     68/push 0/imm32
14163     68/push 0/imm32
14164     89/<- %eax 4/r32/esp
14165     # convert
14166     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
14167     # var out-addr/edx: (addr stmt) = lookup(*out)
14168     (lookup *eax *(eax+4))  # => eax
14169     89/<- %edx 0/r32/eax
14170     # out->tag
14171     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
14172     # out->operation
14173     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
14174     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
14175     # out->inouts->value->name
14176     # . eax = out->inouts
14177     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14178     # . eax = out->inouts->value
14179     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14180     # . eax = out->inouts->value->name
14181     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14182     # .
14183     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
14184     # . epilogue
14185     89/<- %esp 5/r32/ebp
14186     5d/pop-to-ebp
14187     c3/return
14188 
14189 test-parse-mu-stmt-with-comma:
14190     # . prologue
14191     55/push-ebp
14192     89/<- %ebp 4/r32/esp
14193     # setup
14194     8b/-> *Primitive-type-ids 0/r32/eax
14195     89/<- *Type-id 0/r32/eax  # stream-write
14196     (clear-stream _test-input-stream)
14197     (write _test-input-stream "copy-to n, 3\n")
14198     # var vars/ecx: (stack (addr var) 16)
14199     81 5/subop/subtract %esp 0xc0/imm32
14200     68/push 0xc0/imm32/size
14201     68/push 0/imm32/top
14202     89/<- %ecx 4/r32/esp
14203     (clear-stack %ecx)
14204     # var v/edx: (handle var)
14205     68/push 0/imm32
14206     68/push 0/imm32
14207     89/<- %edx 4/r32/esp
14208     # var s/eax: (handle array byte)
14209     68/push 0/imm32
14210     68/push 0/imm32
14211     89/<- %eax 4/r32/esp
14212     # v = new var("n")
14213     (copy-array Heap "n" %eax)
14214     (new-var Heap *eax *(eax+4) %edx)
14215     #
14216     (push %ecx *edx)
14217     (push %ecx *(edx+4))
14218     (push %ecx 0)
14219     # var out/eax: (handle stmt)
14220     68/push 0/imm32
14221     68/push 0/imm32
14222     89/<- %eax 4/r32/esp
14223     # convert
14224     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
14225     # var out-addr/edx: (addr stmt) = lookup(*out)
14226     (lookup *eax *(eax+4))  # => eax
14227     89/<- %edx 0/r32/eax
14228     # out->tag
14229     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
14230     # out->operation
14231     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
14232     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
14233     # out->inouts->value->name
14234     # . eax = out->inouts
14235     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14236     # . eax = out->inouts->value
14237     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14238     # . eax = out->inouts->value->name
14239     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14240     # .
14241     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
14242     # . epilogue
14243     89/<- %esp 5/r32/ebp
14244     5d/pop-to-ebp
14245     c3/return
14246 
14247 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
14248     # . prologue
14249     55/push-ebp
14250     89/<- %ebp 4/r32/esp
14251     # . save registers
14252     50/push-eax
14253     51/push-ecx
14254     # ecx = out
14255     8b/-> *(ebp+0x14) 1/r32/ecx
14256     #
14257     (allocate *(ebp+8) *Var-size %ecx)
14258     # var out-addr/eax: (addr var)
14259     (lookup *ecx *(ecx+4))  # => eax
14260     # out-addr->name = name
14261     8b/-> *(ebp+0xc) 1/r32/ecx
14262     89/<- *eax 1/r32/ecx  # Var-name
14263     8b/-> *(ebp+0x10) 1/r32/ecx
14264     89/<- *(eax+4) 1/r32/ecx  # Var-name
14265 #?     (write-buffered Stderr "var ")
14266 #?     (lookup *(ebp+0xc) *(ebp+0x10))
14267 #?     (write-buffered Stderr %eax)
14268 #?     (write-buffered Stderr " at ")
14269 #?     8b/-> *(ebp+0x14) 1/r32/ecx
14270 #?     (lookup *ecx *(ecx+4))  # => eax
14271 #?     (write-int32-hex-buffered Stderr %eax)
14272 #?     (write-buffered Stderr Newline)
14273 #?     (flush Stderr)
14274 $new-var:end:
14275     # . restore registers
14276     59/pop-to-ecx
14277     58/pop-to-eax
14278     # . epilogue
14279     89/<- %esp 5/r32/ebp
14280     5d/pop-to-ebp
14281     c3/return
14282 
14283 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)
14284     # . prologue
14285     55/push-ebp
14286     89/<- %ebp 4/r32/esp
14287     # . save registers
14288     50/push-eax
14289     51/push-ecx
14290     # if (!is-hex-int?(name)) abort
14291     (is-hex-int? *(ebp+0xc))  # => eax
14292     3d/compare-eax-and 0/imm32/false
14293     0f 84/jump-if-= $new-literal-integer:abort/disp32
14294     # a little more error-checking
14295     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
14296     # out = new var(s)
14297     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
14298     # var out-addr/ecx: (addr var) = lookup(*out)
14299     8b/-> *(ebp+0x10) 0/r32/eax
14300     (lookup *eax *(eax+4))  # => eax
14301     89/<- %ecx 0/r32/eax
14302     # out-addr->block-depth = *Curr-block-depth
14303     8b/-> *Curr-block-depth 0/r32/eax
14304     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
14305     # out-addr->type = new tree()
14306     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
14307     (allocate *(ebp+8) *Type-tree-size %eax)
14308     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14309     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
14310     # nothing else to do; default type is 'literal'
14311 $new-literal-integer:end:
14312     # . reclaim locals
14313     81 0/subop/add %esp 8/imm32
14314     # . restore registers
14315     59/pop-to-ecx
14316     58/pop-to-eax
14317     # . epilogue
14318     89/<- %esp 5/r32/ebp
14319     5d/pop-to-ebp
14320     c3/return
14321 
14322 $new-literal-integer:abort:
14323     (write-buffered *(ebp+0x18) "fn ")
14324     8b/-> *(ebp+0x14) 0/r32/eax
14325     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14326     (write-buffered *(ebp+0x18) %eax)
14327     (write-buffered *(ebp+0x18) ": variable '")
14328     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
14329     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
14330     (flush *(ebp+0x18))
14331     (stop *(ebp+0x1c) 1)
14332     # never gets here
14333 
14334 # precondition: name is a valid hex integer; require a '0x' prefix
14335 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
14336     # . prologue
14337     55/push-ebp
14338     89/<- %ebp 4/r32/esp
14339     # . save registers
14340     50/push-eax
14341     51/push-ecx
14342     52/push-edx
14343     # ecx = name
14344     8b/-> *(ebp+8) 1/r32/ecx
14345     # var start/edx: (addr byte) = name->start
14346     8b/-> *ecx 2/r32/edx
14347     # if (*start == '-') ++start
14348     b8/copy-to-eax 0/imm32
14349     8a/copy-byte *edx 0/r32/AL
14350     3d/compare-eax-and 0x2d/imm32/dash
14351     {
14352       75/jump-if-!= break/disp8
14353       42/increment-edx
14354     }
14355     # var end/ecx: (addr byte) = name->end
14356     8b/-> *(ecx+4) 1/r32/ecx
14357     # var len/eax: int = name->end - name->start
14358     89/<- %eax 1/r32/ecx
14359     29/subtract-from %eax 2/r32/edx
14360     # if (len <= 1) return
14361     3d/compare-eax-with 1/imm32
14362     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
14363 $check-mu-hex-int:length->-1:
14364     # if slice-starts-with?({start, end}, "0x") return
14365     # . var tmp = {start, end}
14366     51/push-ecx
14367     52/push-edx
14368     89/<- %eax 4/r32/esp
14369     # .
14370     (slice-starts-with? %eax "0x")  # => eax
14371     # . reclaim tmp
14372     81 0/subop/add %esp 8/imm32
14373     # .
14374     3d/compare-eax-with 0/imm32/false
14375     75/jump-if-!= $check-mu-hex-int:end/disp8
14376 $check-mu-hex-int:abort:
14377     # otherwise abort
14378     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
14379     (write-slice-buffered *(ebp+0xc) *(ebp+8))
14380     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
14381     (flush *(ebp+0xc))
14382     (stop *(ebp+0x10) 1)
14383 $check-mu-hex-int:end:
14384     # . restore registers
14385     5a/pop-to-edx
14386     59/pop-to-ecx
14387     58/pop-to-eax
14388     # . epilogue
14389     89/<- %esp 5/r32/ebp
14390     5d/pop-to-ebp
14391     c3/return
14392 
14393 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
14394     # . prologue
14395     55/push-ebp
14396     89/<- %ebp 4/r32/esp
14397     # . save registers
14398     50/push-eax
14399     51/push-ecx
14400     # var s/ecx: (handle array byte)
14401     68/push 0/imm32
14402     68/push 0/imm32
14403     89/<- %ecx 4/r32/esp
14404     # s = slice-to-string(name)
14405     (slice-to-string Heap *(ebp+0xc) %ecx)
14406     # allocate to out
14407     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
14408     # var out-addr/ecx: (addr var) = lookup(*out)
14409     8b/-> *(ebp+0x10) 1/r32/ecx
14410     (lookup *ecx *(ecx+4))  # => eax
14411     89/<- %ecx 0/r32/eax
14412     # out-addr->block-depth = *Curr-block-depth
14413     8b/-> *Curr-block-depth 0/r32/eax
14414     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
14415     # out-addr->type/eax = new type
14416     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
14417     (allocate *(ebp+8) *Type-tree-size %eax)
14418     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14419     # nothing else to do; default type is 'literal'
14420     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
14421 $new-literal:end:
14422     # . reclaim locals
14423     81 0/subop/add %esp 8/imm32
14424     # . restore registers
14425     59/pop-to-ecx
14426     58/pop-to-eax
14427     # . epilogue
14428     89/<- %esp 5/r32/ebp
14429     5d/pop-to-ebp
14430     c3/return
14431 
14432 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
14433     # . prologue
14434     55/push-ebp
14435     89/<- %ebp 4/r32/esp
14436     # . save registers
14437     51/push-ecx
14438     # var tmp/ecx: (handle array byte)
14439     68/push 0/imm32
14440     68/push 0/imm32
14441     89/<- %ecx 4/r32/esp
14442     # tmp = slice-to-string(name)
14443     (slice-to-string Heap *(ebp+0xc) %ecx)
14444     # out = new-var(tmp)
14445     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
14446 $new-var-from-slice:end:
14447     # . reclaim locals
14448     81 0/subop/add %esp 8/imm32
14449     # . restore registers
14450     59/pop-to-ecx
14451     # . epilogue
14452     89/<- %esp 5/r32/ebp
14453     5d/pop-to-ebp
14454     c3/return
14455 
14456 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
14457     # . prologue
14458     55/push-ebp
14459     89/<- %ebp 4/r32/esp
14460     # . save registers
14461     50/push-eax
14462     51/push-ecx
14463     #
14464     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
14465     # var out-addr/eax: (addr stmt) = lookup(*out)
14466     8b/-> *(ebp+0x14) 0/r32/eax
14467     (lookup *eax *(eax+4))  # => eax
14468     # out-addr->tag = stmt
14469     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
14470     # result->var = var
14471     8b/-> *(ebp+0xc) 1/r32/ecx
14472     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
14473     8b/-> *(ebp+0x10) 1/r32/ecx
14474     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
14475 $new-var-def:end:
14476     # . restore registers
14477     59/pop-to-ecx
14478     58/pop-to-eax
14479     # . epilogue
14480     89/<- %esp 5/r32/ebp
14481     5d/pop-to-ebp
14482     c3/return
14483 
14484 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
14485     # . prologue
14486     55/push-ebp
14487     89/<- %ebp 4/r32/esp
14488     # . save registers
14489     50/push-eax
14490     # eax = out
14491     8b/-> *(ebp+0x14) 0/r32/eax
14492     #
14493     (allocate *(ebp+8) *Stmt-size %eax)
14494     # var out-addr/eax: (addr stmt) = lookup(*out)
14495     (lookup *eax *(eax+4))  # => eax
14496     # set tag
14497     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
14498     # set output
14499     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
14500     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
14501 $new-reg-var-def:end:
14502     # . restore registers
14503     58/pop-to-eax
14504     # . epilogue
14505     89/<- %esp 5/r32/ebp
14506     5d/pop-to-ebp
14507     c3/return
14508 
14509 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
14510     # . prologue
14511     55/push-ebp
14512     89/<- %ebp 4/r32/esp
14513     # . save registers
14514     50/push-eax
14515     51/push-ecx
14516     57/push-edi
14517     # edi = out
14518     8b/-> *(ebp+0x1c) 7/r32/edi
14519     # *out = new list
14520     (allocate *(ebp+8) *List-size %edi)
14521     # var out-addr/edi: (addr list _type) = lookup(*out)
14522     (lookup *edi *(edi+4))  # => eax
14523     89/<- %edi 0/r32/eax
14524     # out-addr->value = value
14525     8b/-> *(ebp+0xc) 0/r32/eax
14526     89/<- *edi 0/r32/eax  # List-value
14527     8b/-> *(ebp+0x10) 0/r32/eax
14528     89/<- *(edi+4) 0/r32/eax  # List-value
14529     # if (list == null) return
14530     81 7/subop/compare *(ebp+0x14) 0/imm32
14531     74/jump-if-= $append-list:end/disp8
14532     # otherwise append
14533 $append-list:non-empty-list:
14534     # var curr/eax: (addr list _type) = lookup(list)
14535     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
14536     # while (curr->next != null) curr = curr->next
14537     {
14538       81 7/subop/compare *(eax+8) 0/imm32  # List-next
14539       74/jump-if-= break/disp8
14540       # curr = lookup(curr->next)
14541       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
14542       #
14543       eb/jump loop/disp8
14544     }
14545     # edi = out
14546     8b/-> *(ebp+0x1c) 7/r32/edi
14547     # curr->next = out
14548     8b/-> *edi 1/r32/ecx
14549     89/<- *(eax+8) 1/r32/ecx  # List-next
14550     8b/-> *(edi+4) 1/r32/ecx
14551     89/<- *(eax+0xc) 1/r32/ecx  # List-next
14552     # out = list
14553     8b/-> *(ebp+0x14) 1/r32/ecx
14554     89/<- *edi 1/r32/ecx
14555     8b/-> *(ebp+0x18) 1/r32/ecx
14556     89/<- *(edi+4) 1/r32/ecx
14557 $append-list:end:
14558     # . restore registers
14559     5f/pop-to-edi
14560     59/pop-to-ecx
14561     58/pop-to-eax
14562     # . epilogue
14563     89/<- %esp 5/r32/ebp
14564     5d/pop-to-ebp
14565     c3/return
14566 
14567 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
14568     # . prologue
14569     55/push-ebp
14570     89/<- %ebp 4/r32/esp
14571     # . save registers
14572     50/push-eax
14573     51/push-ecx
14574     57/push-edi
14575     # edi = out
14576     8b/-> *(ebp+0x20) 7/r32/edi
14577     # out = new stmt-var
14578     (allocate *(ebp+8) *Stmt-var-size %edi)
14579     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
14580     (lookup *edi *(edi+4))  # => eax
14581     89/<- %ecx 0/r32/eax
14582     # out-addr->value = v
14583     8b/-> *(ebp+0xc) 0/r32/eax
14584     89/<- *ecx 0/r32/eax  # Stmt-var-value
14585     8b/-> *(ebp+0x10) 0/r32/eax
14586     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
14587     # out-addr->is-deref? = is-deref?
14588     8b/-> *(ebp+0x1c) 0/r32/eax
14589     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
14590     # if (vars == null) return result
14591     81 7/subop/compare *(ebp+0x14) 0/imm32/null
14592     74/jump-if-= $append-stmt-var:end/disp8
14593     # otherwise append
14594     # var curr/eax: (addr stmt-var) = lookup(vars)
14595     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
14596     # while (curr->next != null) curr = curr->next
14597     {
14598       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
14599       74/jump-if-= break/disp8
14600       # curr = lookup(curr->next)
14601       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
14602       #
14603       eb/jump loop/disp8
14604     }
14605     # curr->next = out
14606     8b/-> *edi 1/r32/ecx
14607     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
14608     8b/-> *(edi+4) 1/r32/ecx
14609     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
14610     # out = vars
14611     8b/-> *(ebp+0x14) 1/r32/ecx
14612     89/<- *edi 1/r32/ecx
14613     8b/-> *(ebp+0x18) 1/r32/ecx
14614     89/<- *(edi+4) 1/r32/ecx
14615 $append-stmt-var:end:
14616     # . restore registers
14617     5f/pop-to-edi
14618     59/pop-to-ecx
14619     58/pop-to-eax
14620     # . epilogue
14621     89/<- %esp 5/r32/ebp
14622     5d/pop-to-ebp
14623     c3/return
14624 
14625 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
14626     # . prologue
14627     55/push-ebp
14628     89/<- %ebp 4/r32/esp
14629     # . save registers
14630     50/push-eax
14631     56/push-esi
14632     # esi = block
14633     8b/-> *(ebp+0xc) 6/r32/esi
14634     # block->stmts = append(x, block->stmts)
14635     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
14636     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
14637 $append-to-block:end:
14638     # . restore registers
14639     5e/pop-to-esi
14640     58/pop-to-eax
14641     # . epilogue
14642     89/<- %esp 5/r32/ebp
14643     5d/pop-to-ebp
14644     c3/return
14645 
14646 ## Parsing types
14647 # We need to create metadata on user-defined types, and we need to use this
14648 # metadata as we parse instructions.
14649 # However, we also want to allow types to be used before their definitions.
14650 # This means we can't ever assume any type data structures exist.
14651 
14652 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
14653     # . prologue
14654     55/push-ebp
14655     89/<- %ebp 4/r32/esp
14656     # . save registers
14657     50/push-eax
14658     56/push-esi
14659     # var container-type/esi: type-id
14660     (container-type *(ebp+8))  # => eax
14661     89/<- %esi 0/r32/eax
14662     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
14663     68/push 0/imm32
14664     68/push 0/imm32
14665     89/<- %eax 4/r32/esp
14666     (find-or-create-typeinfo %esi %eax)
14667     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
14668     (lookup *eax *(eax+4))  # => eax
14669     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
14670 #?     (write-buffered Stderr "constant: ")
14671 #?     (write-slice-buffered Stderr *(ebp+0xc))
14672 #?     (write-buffered Stderr Newline)
14673 #?     (flush Stderr)
14674     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
14675 #?     8b/-> *(ebp+0x10) 0/r32/eax
14676 #?     (write-buffered Stderr "@")
14677 #?     (lookup *eax *(eax+4))
14678 #?     (write-int32-hex-buffered Stderr %eax)
14679 #?     (lookup *eax *(eax+4))
14680 #?     (write-buffered Stderr %eax)
14681 #?     (write-buffered Stderr Newline)
14682 #?     (flush Stderr)
14683 #?     (write-buffered Stderr "offset: ")
14684 #?     8b/-> *(eax+0x14) 0/r32/eax
14685 #?     (write-int32-hex-buffered Stderr %eax)
14686 #?     (write-buffered Stderr Newline)
14687 #?     (flush Stderr)
14688 $lookup-or-create-constant:end:
14689     # . reclaim locals
14690     81 0/subop/add %esp 8/imm32
14691     # . restore registers
14692     5e/pop-to-esi
14693     58/pop-to-eax
14694     # . epilogue
14695     89/<- %esp 5/r32/ebp
14696     5d/pop-to-ebp
14697     c3/return
14698 
14699 # if addr var:
14700 #   container->var->type->right->left->value
14701 # otherwise
14702 #   container->var->type->value
14703 container-type:  # container: (addr stmt-var) -> result/eax: type-id
14704     # . prologue
14705     55/push-ebp
14706     89/<- %ebp 4/r32/esp
14707     #
14708     8b/-> *(ebp+8) 0/r32/eax
14709     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14710     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14711     {
14712       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
14713       74/jump-if-= break/disp8
14714       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
14715       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
14716     }
14717     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
14718 $container-type:end:
14719     # . epilogue
14720     89/<- %esp 5/r32/ebp
14721     5d/pop-to-ebp
14722     c3/return
14723 
14724 is-container?:  # t: type-id -> result/eax: boolean
14725     # . prologue
14726     55/push-ebp
14727     89/<- %ebp 4/r32/esp
14728     #
14729     8b/-> *(ebp+8) 0/r32/eax
14730     c1/shift 4/subop/left %eax 2/imm8
14731     3b/compare 0/r32/eax *Primitive-type-ids
14732     0f 9d/set-if->= %al
14733     81 4/subop/and %eax 0xff/imm32
14734 $is-container?:end:
14735     # . epilogue
14736     89/<- %esp 5/r32/ebp
14737     5d/pop-to-ebp
14738     c3/return
14739 
14740 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
14741     # . prologue
14742     55/push-ebp
14743     89/<- %ebp 4/r32/esp
14744     # . save registers
14745     50/push-eax
14746     51/push-ecx
14747     52/push-edx
14748     57/push-edi
14749     # edi = out
14750     8b/-> *(ebp+0xc) 7/r32/edi
14751     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
14752     68/push 0/imm32
14753     68/push 0/imm32
14754     89/<- %ecx 4/r32/esp
14755     # find-typeinfo(t, out)
14756     (find-typeinfo *(ebp+8) %edi)
14757     {
14758       # if (*out != 0) break
14759       81 7/subop/compare *edi 0/imm32
14760       0f 85/jump-if-!= break/disp32
14761 $find-or-create-typeinfo:create:
14762       # *out = allocate
14763       (allocate Heap *Typeinfo-size %edi)
14764       # var tmp/eax: (addr typeinfo) = lookup(*out)
14765       (lookup *edi *(edi+4))  # => eax
14766 #?     (write-buffered Stderr "created typeinfo at ")
14767 #?     (write-int32-hex-buffered Stderr %eax)
14768 #?     (write-buffered Stderr " for type-id ")
14769 #?     (write-int32-hex-buffered Stderr *(ebp+8))
14770 #?     (write-buffered Stderr Newline)
14771 #?     (flush Stderr)
14772       # tmp->id = t
14773       8b/-> *(ebp+8) 2/r32/edx
14774       89/<- *eax 2/r32/edx  # Typeinfo-id
14775       # tmp->fields = new table
14776       # . fields = new table
14777       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
14778       # . tmp->fields = fields
14779       8b/-> *ecx 2/r32/edx
14780       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
14781       8b/-> *(ecx+4) 2/r32/edx
14782       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
14783       # tmp->next = Program->types
14784       8b/-> *_Program-types 1/r32/ecx
14785       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
14786       8b/-> *_Program-types->payload 1/r32/ecx
14787       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
14788       # Program->types = out
14789       8b/-> *edi 1/r32/ecx
14790       89/<- *_Program-types 1/r32/ecx
14791       8b/-> *(edi+4) 1/r32/ecx
14792       89/<- *_Program-types->payload 1/r32/ecx
14793     }
14794 $find-or-create-typeinfo:end:
14795     # . reclaim locals
14796     81 0/subop/add %esp 8/imm32
14797     # . restore registers
14798     5f/pop-to-edi
14799     5a/pop-to-edx
14800     59/pop-to-ecx
14801     58/pop-to-eax
14802     # . epilogue
14803     89/<- %esp 5/r32/ebp
14804     5d/pop-to-ebp
14805     c3/return
14806 
14807 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
14808     # . prologue
14809     55/push-ebp
14810     89/<- %ebp 4/r32/esp
14811     # . save registers
14812     50/push-eax
14813     51/push-ecx
14814     52/push-edx
14815     57/push-edi
14816     # ecx = t
14817     8b/-> *(ebp+8) 1/r32/ecx
14818     # edi = out
14819     8b/-> *(ebp+0xc) 7/r32/edi
14820     # *out = Program->types
14821     8b/-> *_Program-types 0/r32/eax
14822     89/<- *edi 0/r32/eax
14823     8b/-> *_Program-types->payload 0/r32/eax
14824     89/<- *(edi+4) 0/r32/eax
14825     {
14826 $find-typeinfo:loop:
14827       # if (*out == 0) break
14828       81 7/subop/compare *edi 0/imm32
14829       74/jump-if-= break/disp8
14830 $find-typeinfo:check:
14831       # var tmp/eax: (addr typeinfo) = lookup(*out)
14832       (lookup *edi *(edi+4))  # => eax
14833       # if (tmp->id == t) break
14834       39/compare *eax 1/r32/ecx  # Typeinfo-id
14835       74/jump-if-= break/disp8
14836 $find-typeinfo:continue:
14837       # *out = tmp->next
14838       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
14839       89/<- *edi 2/r32/edx
14840       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
14841       89/<- *(edi+4) 2/r32/edx
14842       #
14843       eb/jump loop/disp8
14844     }
14845 $find-typeinfo:end:
14846     # . restore registers
14847     5f/pop-to-edi
14848     5a/pop-to-edx
14849     59/pop-to-ecx
14850     58/pop-to-eax
14851     # . epilogue
14852     89/<- %esp 5/r32/ebp
14853     5d/pop-to-ebp
14854     c3/return
14855 
14856 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
14857     # . prologue
14858     55/push-ebp
14859     89/<- %ebp 4/r32/esp
14860     # . save registers
14861     50/push-eax
14862     52/push-edx
14863     57/push-edi
14864     # var dest/edi: (handle typeinfo-entry)
14865     68/push 0/imm32
14866     68/push 0/imm32
14867     89/<- %edi 4/r32/esp
14868     # find-or-create-typeinfo-fields(T, f, dest)
14869     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
14870     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
14871     (lookup *edi *(edi+4))  # => eax
14872     89/<- %edi 0/r32/eax
14873     # if dest-addr->output-var doesn't exist, create it
14874     {
14875       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
14876       0f 85/jump-if-!= break/disp32
14877       # dest-addr->output-var = new var(dummy name, type, -1 offset)
14878       # . var name/eax: (handle array byte) = "field"
14879       68/push 0/imm32
14880       68/push 0/imm32
14881       89/<- %eax 4/r32/esp
14882       (slice-to-string Heap *(ebp+0xc) %eax)
14883       # . new var
14884       8d/copy-address *(edi+0xc) 2/r32/edx
14885       (new-var Heap  *eax *(eax+4)  %edx)
14886       # . reclaim name
14887       81 0/subop/add %esp 8/imm32
14888       # var result/edx: (addr var) = lookup(dest-addr->output-var)
14889       (lookup *(edi+0xc) *(edi+0x10))  # => eax
14890       89/<- %edx 0/r32/eax
14891       # result->type = new constant type
14892       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
14893       (allocate Heap *Type-tree-size %eax)
14894       (lookup *(edx+8) *(edx+0xc))  # => eax
14895       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
14896       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
14897       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
14898       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
14899       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
14900       # result->offset isn't filled out yet
14901       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
14902     }
14903     # out = dest-addr->output-var
14904     8b/-> *(ebp+0x10) 2/r32/edx
14905     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
14906     89/<- *edx 0/r32/eax
14907     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
14908     89/<- *(edx+4) 0/r32/eax
14909 $find-or-create-typeinfo-output-var:end:
14910     # . reclaim locals
14911     81 0/subop/add %esp 8/imm32
14912     # . restore registers
14913     5f/pop-to-edi
14914     5a/pop-to-edx
14915     58/pop-to-eax
14916     # . epilogue
14917     89/<- %esp 5/r32/ebp
14918     5d/pop-to-ebp
14919     c3/return
14920 
14921 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
14922     # . prologue
14923     55/push-ebp
14924     89/<- %ebp 4/r32/esp
14925     # . save registers
14926     50/push-eax
14927     56/push-esi
14928     57/push-edi
14929     # eax = lookup(T->fields)
14930     8b/-> *(ebp+8) 0/r32/eax
14931     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
14932     # edi = out
14933     8b/-> *(ebp+0x10) 7/r32/edi
14934     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
14935     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
14936     89/<- %esi 0/r32/eax
14937     # if src doesn't exist, allocate it
14938     {
14939       81 7/subop/compare *esi 0/imm32
14940       75/jump-if-!= break/disp8
14941       (allocate Heap *Typeinfo-entry-size %esi)
14942 #?       (write-buffered Stderr "handle at ")
14943 #?       (write-int32-hex-buffered Stderr %esi)
14944 #?       (write-buffered Stderr ": ")
14945 #?       (write-int32-hex-buffered Stderr *esi)
14946 #?       (write-buffered Stderr " ")
14947 #?       (write-int32-hex-buffered Stderr *(esi+4))
14948 #?       (write-buffered Stderr Newline)
14949 #?       (flush Stderr)
14950 #?       (lookup *esi *(esi+4))
14951 #?       (write-buffered Stderr "created typeinfo fields at ")
14952 #?       (write-int32-hex-buffered Stderr %esi)
14953 #?       (write-buffered Stderr " for ")
14954 #?       (write-int32-hex-buffered Stderr *(ebp+8))
14955 #?       (write-buffered Stderr Newline)
14956 #?       (flush Stderr)
14957     }
14958     # *out = src
14959     # . *edi = *src
14960     8b/-> *esi 0/r32/eax
14961     89/<- *edi 0/r32/eax
14962     8b/-> *(esi+4) 0/r32/eax
14963     89/<- *(edi+4) 0/r32/eax
14964 $find-or-create-typeinfo-fields:end:
14965     # . restore registers
14966     5f/pop-to-edi
14967     5e/pop-to-esi
14968     58/pop-to-eax
14969     # . epilogue
14970     89/<- %esp 5/r32/ebp
14971     5d/pop-to-ebp
14972     c3/return
14973 
14974 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
14975     # pseudocode:
14976     #   var line: (stream byte 512)
14977     #   curr-index = 0
14978     #   while true
14979     #     clear-stream(line)
14980     #     read-line-buffered(in, line)
14981     #     if line->write == 0
14982     #       abort
14983     #     word-slice = next-mu-token(line)
14984     #     if slice-empty?(word-slice)               # end of line
14985     #       continue
14986     #     if slice-equal?(word-slice, "}")
14987     #       break
14988     #     var v: (handle var) = parse-var-with-type(word-slice, line)
14989     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
14990     #     TODO: ensure that r->first is null
14991     #     r->index = curr-index
14992     #     curr-index++
14993     #     r->input-var = v
14994     #     if r->output-var == 0
14995     #       r->output-var = new literal
14996     #     TODO: ensure nothing else in line
14997     # t->total-size-in-bytes = -2 (not yet initialized)
14998     #
14999     # . prologue
15000     55/push-ebp
15001     89/<- %ebp 4/r32/esp
15002     # var curr-index: int at *(ebp-4)
15003     68/push 0/imm32
15004     # . save registers
15005     50/push-eax
15006     51/push-ecx
15007     52/push-edx
15008     53/push-ebx
15009     56/push-esi
15010     57/push-edi
15011     # edi = t
15012     8b/-> *(ebp+0xc) 7/r32/edi
15013     # var line/ecx: (stream byte 512)
15014     81 5/subop/subtract %esp 0x200/imm32
15015     68/push 0x200/imm32/size
15016     68/push 0/imm32/read
15017     68/push 0/imm32/write
15018     89/<- %ecx 4/r32/esp
15019     # var word-slice/edx: slice
15020     68/push 0/imm32/end
15021     68/push 0/imm32/start
15022     89/<- %edx 4/r32/esp
15023     # var v/esi: (handle var)
15024     68/push 0/imm32
15025     68/push 0/imm32
15026     89/<- %esi 4/r32/esp
15027     # var r/ebx: (handle typeinfo-entry)
15028     68/push 0/imm32
15029     68/push 0/imm32
15030     89/<- %ebx 4/r32/esp
15031     {
15032 $populate-mu-type:line-loop:
15033       (clear-stream %ecx)
15034       (read-line-buffered *(ebp+8) %ecx)
15035       # if (line->write == 0) abort
15036       81 7/subop/compare *ecx 0/imm32
15037       0f 84/jump-if-= $populate-mu-type:error1/disp32
15038 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
15044       (next-mu-token %ecx %edx)
15045       # if slice-empty?(word-slice) continue
15046       (slice-empty? %edx)  # => eax
15047       3d/compare-eax-and 0/imm32
15048       0f 85/jump-if-!= loop/disp32
15049       # if slice-equal?(word-slice, "}") break
15050       (slice-equal? %edx "}")
15051       3d/compare-eax-and 0/imm32
15052       0f 85/jump-if-!= break/disp32
15053 $populate-mu-type:parse-element:
15054       # v = parse-var-with-type(word-slice, first-line)
15055       # must do this first to strip the trailing ':' from word-slice before
15056       # using it in find-or-create-typeinfo-fields below
15057       # TODO: clean up that mutation in parse-var-with-type
15058       (parse-var-with-type %edx %ecx %esi *(ebp+0x10) *(ebp+0x14))
15059       # if v is an addr, abort
15060       (lookup *esi *(esi+4))  # => eax
15061       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15062       (is-mu-addr-type? %eax)  # => eax
15063       3d/compare-eax-and 0/imm32/false
15064       0f 85/jump-if-!= $populate-mu-type:error2/disp32
15065       # if v is an array, abort  (we could support it, but initialization gets complex)
15066       (lookup *esi *(esi+4))  # => eax
15067       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15068       (is-mu-array-type? %eax)  # => eax
15069       3d/compare-eax-and 0/imm32/false
15070       0f 85/jump-if-!= $populate-mu-type:error3/disp32
15071       # if v is a byte, abort
15072       (lookup *esi *(esi+4))  # => eax
15073       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15074       (is-simple-mu-type? %eax 8)  # byte => eax
15075       3d/compare-eax-and 0/imm32/false
15076       0f 85/jump-if-!= $populate-mu-type:error4/disp32
15077       # if v is a slice, abort
15078       (lookup *esi *(esi+4))  # => eax
15079       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15080       (is-simple-mu-type? %eax 0xc)  # slice => eax
15081       3d/compare-eax-and 0/imm32/false
15082       0f 85/jump-if-!= $populate-mu-type:error5/disp32
15083       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
15084       (lookup *esi *(esi+4))  # => eax
15085       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15086       (is-mu-stream-type? %eax)  # => eax
15087       3d/compare-eax-and 0/imm32/false
15088       0f 85/jump-if-!= $populate-mu-type:error6/disp32
15089       # var tmp/ecx
15090       51/push-ecx
15091 $populate-mu-type:create-typeinfo-fields:
15092       # var r/ebx: (handle typeinfo-entry)
15093       (find-or-create-typeinfo-fields %edi %edx %ebx)
15094       # r->index = curr-index
15095       (lookup *ebx *(ebx+4))  # => eax
15096       8b/-> *(ebp-4) 1/r32/ecx
15097 #?       (write-buffered Stderr "saving index ")
15098 #?       (write-int32-hex-buffered Stderr %ecx)
15099 #?       (write-buffered Stderr " at ")
15100 #?       (write-int32-hex-buffered Stderr %edi)
15101 #?       (write-buffered Stderr Newline)
15102 #?       (flush Stderr)
15103       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
15104       # ++curr-index
15105       ff 0/subop/increment *(ebp-4)
15106 $populate-mu-type:set-input-type:
15107       # r->input-var = v
15108       8b/-> *esi 1/r32/ecx
15109       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
15110       8b/-> *(esi+4) 1/r32/ecx
15111       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
15112       # restore line
15113       59/pop-to-ecx
15114       {
15115 $populate-mu-type:create-output-type:
15116         # if (r->output-var == 0) create a new var with some placeholder data
15117         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
15118         75/jump-if-!= break/disp8
15119         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
15120         (new-literal Heap %edx %eax)
15121       }
15122       e9/jump loop/disp32
15123     }
15124 $populate-mu-type:invalidate-total-size-in-bytes:
15125     # Offsets and total size may not be accurate here since we may not yet
15126     # have encountered the element types.
15127     # We'll recompute them separately after parsing the entire program.
15128     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
15129 $populate-mu-type:end:
15130     # . reclaim locals
15131     81 0/subop/add %esp 0x224/imm32
15132     # . restore registers
15133     5f/pop-to-edi
15134     5e/pop-to-esi
15135     5b/pop-to-ebx
15136     5a/pop-to-edx
15137     59/pop-to-ecx
15138     58/pop-to-eax
15139     # reclaim curr-index
15140     81 0/subop/add %esp 4/imm32
15141     # . epilogue
15142     89/<- %esp 5/r32/ebp
15143     5d/pop-to-ebp
15144     c3/return
15145 
15146 $populate-mu-type:error1:
15147     # error("incomplete type definition '" t->name "'\n")
15148     (write-buffered *(ebp+0x10) "incomplete type definition '")
15149     (type-name *edi)  # Typeinfo-id => eax
15150     (write-buffered *(ebp+0x10) %eax)
15151     (write-buffered *(ebp+0x10) "\n")
15152     (flush *(ebp+0x10))
15153     (stop *(ebp+0x14) 1)
15154     # never gets here
15155 
15156 $populate-mu-type:error2:
15157     (write-buffered *(ebp+0x10) "type ")
15158     (type-name *edi)  # Typeinfo-id => eax
15159     (write-buffered *(ebp+0x10) %eax)
15160     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
15161     (flush *(ebp+0x10))
15162     (stop *(ebp+0x14) 1)
15163     # never gets here
15164 
15165 $populate-mu-type:error3:
15166     (write-buffered *(ebp+0x10) "type ")
15167     (type-name *edi)  # Typeinfo-id => eax
15168     (write-buffered *(ebp+0x10) %eax)
15169     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
15170     (flush *(ebp+0x10))
15171     (stop *(ebp+0x14) 1)
15172     # never gets here
15173 
15174 $populate-mu-type:error4:
15175     (write-buffered *(ebp+0x10) "type ")
15176     (type-name *edi)  # Typeinfo-id => eax
15177     (write-buffered *(ebp+0x10) %eax)
15178     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
15179     (flush *(ebp+0x10))
15180     (stop *(ebp+0x14) 1)
15181     # never gets here
15182 
15183 $populate-mu-type:error5:
15184     (write-buffered *(ebp+0x10) "type ")
15185     (type-name *edi)  # Typeinfo-id => eax
15186     (write-buffered *(ebp+0x10) %eax)
15187     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
15188     (flush *(ebp+0x10))
15189     (stop *(ebp+0x14) 1)
15190     # never gets here
15191 
15192 $populate-mu-type:error6:
15193     (write-buffered *(ebp+0x10) "type ")
15194     (type-name *edi)  # Typeinfo-id => eax
15195     (write-buffered *(ebp+0x10) %eax)
15196     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
15197     (flush *(ebp+0x10))
15198     (stop *(ebp+0x14) 1)
15199     # never gets here
15200 
15201 type-name:  # index: int -> result/eax: (addr array byte)
15202     # . prologue
15203     55/push-ebp
15204     89/<- %ebp 4/r32/esp
15205     #
15206     (index Type-id *(ebp+8))
15207 $type-name:end:
15208     # . epilogue
15209     89/<- %esp 5/r32/ebp
15210     5d/pop-to-ebp
15211     c3/return
15212 
15213 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
15214     # . prologue
15215     55/push-ebp
15216     89/<- %ebp 4/r32/esp
15217     # . save registers
15218     56/push-esi
15219     # TODO: bounds-check index
15220     # esi = arr
15221     8b/-> *(ebp+8) 6/r32/esi
15222     # eax = index
15223     8b/-> *(ebp+0xc) 0/r32/eax
15224     # eax = *(arr + 12 + index)
15225     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
15226 $index:end:
15227     # . restore registers
15228     5e/pop-to-esi
15229     # . epilogue
15230     89/<- %esp 5/r32/ebp
15231     5d/pop-to-ebp
15232     c3/return
15233 
15234 #######################################################
15235 # Compute type sizes
15236 #######################################################
15237 
15238 # Compute the sizes of all user-defined types.
15239 # We'll need the sizes of their elements, which may be other user-defined
15240 # types, which we will compute as needed.
15241 
15242 # Initially, all user-defined types have their sizes set to -2 (invalid)
15243 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
15244     # . prologue
15245     55/push-ebp
15246     89/<- %ebp 4/r32/esp
15247 $populate-mu-type-sizes:total-sizes:
15248     # var curr/eax: (addr typeinfo) = lookup(Program->types)
15249     (lookup *_Program-types *_Program-types->payload)  # => eax
15250     {
15251       # if (curr == null) break
15252       3d/compare-eax-and 0/imm32/null
15253       74/jump-if-= break/disp8
15254       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
15255       # curr = lookup(curr->next)
15256       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
15257       eb/jump loop/disp8
15258     }
15259 $populate-mu-type-sizes:offsets:
15260     # curr = *Program->types
15261     (lookup *_Program-types *_Program-types->payload)  # => eax
15262     {
15263       # if (curr == null) break
15264       3d/compare-eax-and 0/imm32/null
15265       74/jump-if-= break/disp8
15266       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
15267       # curr = curr->next
15268       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
15269       eb/jump loop/disp8
15270     }
15271 $populate-mu-type-sizes:end:
15272     # . epilogue
15273     89/<- %esp 5/r32/ebp
15274     5d/pop-to-ebp
15275     c3/return
15276 
15277 # compute sizes of all fields, recursing as necessary
15278 # sum up all their sizes to arrive at total size
15279 # fields may be out of order, but that doesn't affect the answer
15280 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
15281     # . prologue
15282     55/push-ebp
15283     89/<- %ebp 4/r32/esp
15284     # . save registers
15285     50/push-eax
15286     51/push-ecx
15287     52/push-edx
15288     56/push-esi
15289     57/push-edi
15290     # esi = T
15291     8b/-> *(ebp+8) 6/r32/esi
15292     # if T is already computed, return
15293     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
15294     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
15295     # if T is being computed, abort
15296     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
15297     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
15298     # tag T (-2 to -1) to avoid infinite recursion
15299     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
15300     # var total-size/edi: int = 0
15301     bf/copy-to-edi 0/imm32
15302     # - for every field, if it's a user-defined type, compute its size
15303     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
15304     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
15305     89/<- %ecx 0/r32/eax
15306     # var table-size/edx: int = table->write
15307     8b/-> *ecx 2/r32/edx  # stream-write
15308     # var curr/ecx: (addr table_row) = table->data
15309     8d/copy-address *(ecx+0xc) 1/r32/ecx
15310     # var max/edx: (addr table_row) = table->data + table->write
15311     8d/copy-address *(ecx+edx) 2/r32/edx
15312     {
15313 $populate-mu-type-sizes-in-type:loop:
15314       # if (curr >= max) break
15315       39/compare %ecx 2/r32/edx
15316       73/jump-if-addr>= break/disp8
15317       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
15318       (lookup *(ecx+8) *(ecx+0xc))  # => eax
15319       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
15320       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
15321       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
15322       # compute size of t->input-var
15323       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
15324       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
15325       # result += eax
15326       01/add-to %edi 0/r32/eax
15327       # curr += row-size
15328       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
15329       #
15330       eb/jump loop/disp8
15331     }
15332     # - save result
15333     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
15334 $populate-mu-type-sizes-in-type:end:
15335     # . restore registers
15336     5f/pop-to-edi
15337     5e/pop-to-esi
15338     5a/pop-to-edx
15339     59/pop-to-ecx
15340     58/pop-to-eax
15341     # . epilogue
15342     89/<- %esp 5/r32/ebp
15343     5d/pop-to-ebp
15344     c3/return
15345 
15346 $populate-mu-type-sizes-in-type:abort:
15347     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
15348     (flush *(ebp+0xc))
15349     (stop *(ebp+0x10) 1)
15350     # never gets here
15351 
15352 # Analogous to size-of, except we need to compute what size-of can just read
15353 # off the right data structures.
15354 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
15355     # . prologue
15356     55/push-ebp
15357     89/<- %ebp 4/r32/esp
15358     # . push registers
15359     51/push-ecx
15360     # var t/ecx: (addr type-tree) = lookup(v->type)
15361     8b/-> *(ebp+8) 1/r32/ecx
15362     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
15363     89/<- %ecx 0/r32/eax
15364     # if (t->is-atom == false) t = lookup(t->left)
15365     {
15366       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
15367       75/jump-if-!= break/disp8
15368       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15369       89/<- %ecx 0/r32/eax
15370     }
15371     # TODO: ensure t is an atom
15372     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
15373 $compute-size-of-var:end:
15374     # . restore registers
15375     59/pop-to-ecx
15376     # . epilogue
15377     89/<- %esp 5/r32/ebp
15378     5d/pop-to-ebp
15379     c3/return
15380 
15381 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
15382     # . prologue
15383     55/push-ebp
15384     89/<- %ebp 4/r32/esp
15385     # . save registers
15386     51/push-ecx
15387     # var out/ecx: (handle typeinfo)
15388     68/push 0/imm32
15389     68/push 0/imm32
15390     89/<- %ecx 4/r32/esp
15391     # eax = t
15392     8b/-> *(ebp+8) 0/r32/eax
15393     # if t is a literal, return 0
15394     3d/compare-eax-and 0/imm32/literal
15395     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
15396     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
15397     3d/compare-eax-and 8/imm32/byte
15398     {
15399       75/jump-if-!= break/disp8
15400       b8/copy-to-eax 4/imm32
15401       eb/jump $compute-size-of-type-id:end/disp8
15402     }
15403     # if t is a handle, return 8
15404     3d/compare-eax-and 4/imm32/handle
15405     {
15406       75/jump-if-!= break/disp8
15407       b8/copy-to-eax 8/imm32
15408       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
15409     }
15410     # if t is a slice, return 8
15411     3d/compare-eax-and 0xc/imm32/slice
15412     {
15413       75/jump-if-!= break/disp8
15414       b8/copy-to-eax 8/imm32
15415       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
15416     }
15417     # if t is a user-defined type, compute its size
15418     # TODO: support non-atom type
15419     (find-typeinfo %eax %ecx)
15420     {
15421       81 7/subop/compare *ecx 0/imm32
15422       74/jump-if-= break/disp8
15423 $compute-size-of-type-id:user-defined:
15424       (lookup *ecx *(ecx+4))  # => eax
15425       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
15426       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
15427       eb/jump $compute-size-of-type-id:end/disp8
15428     }
15429     # otherwise return the word size
15430     b8/copy-to-eax 4/imm32
15431 $compute-size-of-type-id:end:
15432     # . reclaim locals
15433     81 0/subop/add %esp 8/imm32
15434     # . restore registers
15435     59/pop-to-ecx
15436     # . epilogue
15437     89/<- %esp 5/r32/ebp
15438     5d/pop-to-ebp
15439     c3/return
15440 
15441 # at this point we have total sizes for all user-defined types
15442 # compute offsets for each element
15443 # complication: fields may be out of order
15444 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
15445     # . prologue
15446     55/push-ebp
15447     89/<- %ebp 4/r32/esp
15448     # . save registers
15449     50/push-eax
15450     51/push-ecx
15451     52/push-edx
15452     53/push-ebx
15453     56/push-esi
15454     57/push-edi
15455 #?     (dump-typeinfos "aaa\n")
15456     # var curr-offset/edi: int = 0
15457     bf/copy-to-edi 0/imm32
15458     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
15459     8b/-> *(ebp+8) 1/r32/ecx
15460     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
15461     89/<- %ecx 0/r32/eax
15462     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
15463     8b/-> *ecx 2/r32/edx  # stream-write
15464     c1 5/subop/shift-right-logical  %edx 4/imm8
15465     # var i/ebx: int = 0
15466     bb/copy-to-ebx 0/imm32
15467     {
15468 $populate-mu-type-offsets:loop:
15469       39/compare %ebx 2/r32/edx
15470       0f 8d/jump-if->= break/disp32
15471 #?       (write-buffered Stderr "looking up index ")
15472 #?       (write-int32-hex-buffered Stderr %ebx)
15473 #?       (write-buffered Stderr " in ")
15474 #?       (write-int32-hex-buffered Stderr *(ebp+8))
15475 #?       (write-buffered Stderr Newline)
15476 #?       (flush Stderr)
15477       # var v/esi: (addr typeinfo-entry)
15478       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
15479       89/<- %esi 0/r32/eax
15480       # if v is null, silently move on; we'll emit a nice error message while type-checking
15481       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
15482       74/jump-if-= $populate-mu-type-offsets:end/disp8
15483       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
15484       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
15485       74/jump-if-= $populate-mu-type-offsets:end/disp8
15486       # v->output-var->offset = curr-offset
15487       # . eax: (addr var)
15488       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
15489       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
15490       # curr-offset += size-of(v->input-var)
15491       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
15492       (size-of %eax)  # => eax
15493       01/add-to %edi 0/r32/eax
15494       # ++i
15495       43/increment-ebx
15496       e9/jump loop/disp32
15497     }
15498 $populate-mu-type-offsets:end:
15499     # . restore registers
15500     5f/pop-to-edi
15501     5e/pop-to-esi
15502     5b/pop-to-ebx
15503     5a/pop-to-edx
15504     59/pop-to-ecx
15505     58/pop-to-eax
15506     # . epilogue
15507     89/<- %esp 5/r32/ebp
15508     5d/pop-to-ebp
15509     c3/return
15510 
15511 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)
15512     # . prologue
15513     55/push-ebp
15514     89/<- %ebp 4/r32/esp
15515     # . save registers
15516     51/push-ecx
15517     52/push-edx
15518     53/push-ebx
15519     56/push-esi
15520     57/push-edi
15521     # esi = table
15522     8b/-> *(ebp+8) 6/r32/esi
15523     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
15524     8d/copy-address *(esi+0xc) 1/r32/ecx
15525     # var max/edx: (addr byte) = &table->data[table->write]
15526     8b/-> *esi 2/r32/edx
15527     8d/copy-address *(ecx+edx) 2/r32/edx
15528     {
15529 $locate-typeinfo-entry-with-index:loop:
15530       39/compare %ecx 2/r32/edx
15531       73/jump-if-addr>= break/disp8
15532       # var v/eax: (addr typeinfo-entry)
15533       (lookup *(ecx+8) *(ecx+0xc))  # => eax
15534       # if (v->index == idx) return v
15535       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
15536 #?       (write-buffered Stderr "comparing ")
15537 #?       (write-int32-hex-buffered Stderr %ebx)
15538 #?       (write-buffered Stderr " and ")
15539 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
15540 #?       (write-buffered Stderr Newline)
15541 #?       (flush Stderr)
15542       39/compare *(ebp+0xc) 3/r32/ebx
15543       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
15544       # curr += Typeinfo-entry-size
15545       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
15546       #
15547       eb/jump loop/disp8
15548     }
15549     # return 0
15550     b8/copy-to-eax 0/imm32
15551 $locate-typeinfo-entry-with-index:end:
15552 #?     (write-buffered Stderr "returning ")
15553 #?     (write-int32-hex-buffered Stderr %eax)
15554 #?     (write-buffered Stderr Newline)
15555 #?     (flush Stderr)
15556     # . restore registers
15557     5f/pop-to-edi
15558     5e/pop-to-esi
15559     5b/pop-to-ebx
15560     5a/pop-to-edx
15561     59/pop-to-ecx
15562     # . epilogue
15563     89/<- %esp 5/r32/ebp
15564     5d/pop-to-ebp
15565     c3/return
15566 
15567 dump-typeinfos:  # hdr: (addr array byte)
15568     # . prologue
15569     55/push-ebp
15570     89/<- %ebp 4/r32/esp
15571     # . save registers
15572     50/push-eax
15573     #
15574     (write-buffered Stderr *(ebp+8))
15575     (flush Stderr)
15576     # var curr/eax: (addr typeinfo) = lookup(Program->types)
15577     (lookup *_Program-types *_Program-types->payload)  # => eax
15578     {
15579       # if (curr == null) break
15580       3d/compare-eax-and 0/imm32
15581       74/jump-if-= break/disp8
15582       (write-buffered Stderr "---\n")
15583       (flush Stderr)
15584       (dump-typeinfo %eax)
15585       # curr = lookup(curr->next)
15586       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
15587       eb/jump loop/disp8
15588     }
15589 $dump-typeinfos:end:
15590     # . restore registers
15591     58/pop-to-eax
15592     # . epilogue
15593     89/<- %esp 5/r32/ebp
15594     5d/pop-to-ebp
15595     c3/return
15596 
15597 dump-typeinfo:  # in: (addr typeinfo)
15598     # . prologue
15599     55/push-ebp
15600     89/<- %ebp 4/r32/esp
15601     # . save registers
15602     50/push-eax
15603     51/push-ecx
15604     52/push-edx
15605     53/push-ebx
15606     56/push-esi
15607     57/push-edi
15608     # esi = in
15609     8b/-> *(ebp+8) 6/r32/esi
15610     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
15611     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
15612     89/<- %ecx 0/r32/eax
15613     (write-buffered Stderr "id:")
15614     (write-int32-hex-buffered Stderr *esi)
15615     (write-buffered Stderr "\n")
15616     (write-buffered Stderr "fields @ ")
15617     (write-int32-hex-buffered Stderr %ecx)
15618     (write-buffered Stderr Newline)
15619     (flush Stderr)
15620     (write-buffered Stderr "  write: ")
15621     (write-int32-hex-buffered Stderr *ecx)
15622     (write-buffered Stderr Newline)
15623     (flush Stderr)
15624     (write-buffered Stderr "  read: ")
15625     (write-int32-hex-buffered Stderr *(ecx+4))
15626     (write-buffered Stderr Newline)
15627     (flush Stderr)
15628     (write-buffered Stderr "  size: ")
15629     (write-int32-hex-buffered Stderr *(ecx+8))
15630     (write-buffered Stderr Newline)
15631     (flush Stderr)
15632     # var table-size/edx: int = table->write
15633     8b/-> *ecx 2/r32/edx  # stream-write
15634     # var curr/ecx: (addr table_row) = table->data
15635     8d/copy-address *(ecx+0xc) 1/r32/ecx
15636     # var max/edx: (addr table_row) = table->data + table->write
15637     8d/copy-address *(ecx+edx) 2/r32/edx
15638     {
15639 $dump-typeinfo:loop:
15640       # if (curr >= max) break
15641       39/compare %ecx 2/r32/edx
15642       0f 83/jump-if-addr>= break/disp32
15643       (write-buffered Stderr "  row:\n")
15644       (write-buffered Stderr "    key: ")
15645       (write-int32-hex-buffered Stderr *ecx)
15646       (write-buffered Stderr ",")
15647       (write-int32-hex-buffered Stderr *(ecx+4))
15648       (write-buffered Stderr " = '")
15649       (lookup *ecx *(ecx+4))
15650       (write-buffered Stderr %eax)
15651       (write-buffered Stderr "' @ ")
15652       (write-int32-hex-buffered Stderr %eax)
15653       (write-buffered Stderr Newline)
15654       (flush Stderr)
15655       (write-buffered Stderr "    value: ")
15656       (write-int32-hex-buffered Stderr *(ecx+8))
15657       (write-buffered Stderr ",")
15658       (write-int32-hex-buffered Stderr *(ecx+0xc))
15659       (write-buffered Stderr " = typeinfo-entry@")
15660       (lookup *(ecx+8) *(ecx+0xc))
15661       (write-int32-hex-buffered Stderr %eax)
15662       (write-buffered Stderr Newline)
15663       (flush Stderr)
15664       (write-buffered Stderr "        input var@")
15665       (dump-var 5 %eax)
15666       (lookup *(ecx+8) *(ecx+0xc))
15667       (write-buffered Stderr "        index: ")
15668       (write-int32-hex-buffered Stderr *(eax+8))
15669       (write-buffered Stderr Newline)
15670       (flush Stderr)
15671       (write-buffered Stderr "        output var@")
15672       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
15673       (dump-var 5 %eax)
15674       (flush Stderr)
15675       # curr += row-size
15676       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
15677       #
15678       e9/jump loop/disp32
15679     }
15680 $dump-typeinfo:end:
15681     # . restore registers
15682     5f/pop-to-edi
15683     5e/pop-to-esi
15684     5b/pop-to-ebx
15685     5a/pop-to-edx
15686     59/pop-to-ecx
15687     58/pop-to-eax
15688     # . epilogue
15689     89/<- %esp 5/r32/ebp
15690     5d/pop-to-ebp
15691     c3/return
15692 
15693 dump-var:  # indent: int, v: (addr handle var)
15694     # . prologue
15695     55/push-ebp
15696     89/<- %ebp 4/r32/esp
15697     # . save registers
15698     50/push-eax
15699     53/push-ebx
15700     # eax = v
15701     8b/-> *(ebp+0xc) 0/r32/eax
15702     #
15703     (write-int32-hex-buffered Stderr *eax)
15704     (write-buffered Stderr ",")
15705     (write-int32-hex-buffered Stderr *(eax+4))
15706     (write-buffered Stderr "->")
15707     (lookup *eax *(eax+4))
15708     (write-int32-hex-buffered Stderr %eax)
15709     (write-buffered Stderr Newline)
15710     (flush Stderr)
15711     {
15712       3d/compare-eax-and 0/imm32
15713       0f 84/jump-if-= break/disp32
15714       (emit-indent Stderr *(ebp+8))
15715       (write-buffered Stderr "name: ")
15716       89/<- %ebx 0/r32/eax
15717       (write-int32-hex-buffered Stderr *ebx)  # Var-name
15718       (write-buffered Stderr ",")
15719       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
15720       (write-buffered Stderr "->")
15721       (lookup *ebx *(ebx+4))  # Var-name
15722       (write-int32-hex-buffered Stderr %eax)
15723       {
15724         3d/compare-eax-and 0/imm32
15725         74/jump-if-= break/disp8
15726         (write-buffered Stderr Space)
15727         (write-buffered Stderr %eax)
15728       }
15729       (write-buffered Stderr Newline)
15730       (flush Stderr)
15731       (emit-indent Stderr *(ebp+8))
15732       (write-buffered Stderr "block depth: ")
15733       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
15734       (write-buffered Stderr Newline)
15735       (flush Stderr)
15736       (emit-indent Stderr *(ebp+8))
15737       (write-buffered Stderr "stack offset: ")
15738       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
15739       (write-buffered Stderr Newline)
15740       (flush Stderr)
15741       (emit-indent Stderr *(ebp+8))
15742       (write-buffered Stderr "reg: ")
15743       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
15744       (write-buffered Stderr ",")
15745       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
15746       (write-buffered Stderr "->")
15747       (flush Stderr)
15748       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
15749       (write-int32-hex-buffered Stderr %eax)
15750       {
15751         3d/compare-eax-and 0/imm32
15752         74/jump-if-= break/disp8
15753         (write-buffered Stderr Space)
15754         (write-buffered Stderr %eax)
15755       }
15756       (write-buffered Stderr Newline)
15757       (flush Stderr)
15758     }
15759 $dump-var:end:
15760     # . restore registers
15761     5b/pop-to-ebx
15762     58/pop-to-eax
15763     # . epilogue
15764     89/<- %esp 5/r32/ebp
15765     5d/pop-to-ebp
15766     c3/return
15767 
15768 #######################################################
15769 # Type-checking
15770 #######################################################
15771 
15772 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
15773     # . prologue
15774     55/push-ebp
15775     89/<- %ebp 4/r32/esp
15776     # . save registers
15777     50/push-eax
15778     # var curr/eax: (addr function) = lookup(Program->functions)
15779     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15780     {
15781 $check-mu-types:loop:
15782       # if (curr == null) break
15783       3d/compare-eax-and 0/imm32
15784       0f 84/jump-if-= break/disp32
15785 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
15793       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
15794       # curr = lookup(curr->next)
15795       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
15796       e9/jump loop/disp32
15797     }
15798 $check-mu-types:end:
15799     # . restore registers
15800     58/pop-to-eax
15801     # . epilogue
15802     89/<- %esp 5/r32/ebp
15803     5d/pop-to-ebp
15804     c3/return
15805 
15806 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15807     # . prologue
15808     55/push-ebp
15809     89/<- %ebp 4/r32/esp
15810     # . save registers
15811     50/push-eax
15812     56/push-esi
15813     # esi = f
15814     8b/-> *(ebp+8) 6/r32/esi
15815     # outputs
15816     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
15817     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
15818     # body
15819     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
15820     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
15821     # if function has no outputs, we're done
15822     81 7/subop/compare *(esi+0x10) 0/imm32
15823     74/jump-if-= $check-mu-function:end/disp8
15824     # some final checks on body
15825     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
15826     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
15827 $check-mu-function:end:
15828     # . restore registers
15829     5e/pop-to-esi
15830     58/pop-to-eax
15831     # . epilogue
15832     89/<- %esp 5/r32/ebp
15833     5d/pop-to-ebp
15834     c3/return
15835 
15836 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15837     # . prologue
15838     55/push-ebp
15839     89/<- %ebp 4/r32/esp
15840     # . save registers
15841     50/push-eax
15842     # eax = block
15843     8b/-> *(ebp+8) 0/r32/eax
15844     # var stmts/eax: (addr list stmt) = lookup(block->statements)
15845     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
15846     #
15847     {
15848 $check-mu-block:check-empty:
15849       3d/compare-eax-and 0/imm32
15850       0f 84/jump-if-= break/disp32
15851       # emit block->statements
15852       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15853     }
15854 $check-mu-block:end:
15855     # . restore registers
15856     58/pop-to-eax
15857     # . epilogue
15858     89/<- %esp 5/r32/ebp
15859     5d/pop-to-ebp
15860     c3/return
15861 
15862 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15863     # . prologue
15864     55/push-ebp
15865     89/<- %ebp 4/r32/esp
15866     # . save registers
15867     50/push-eax
15868     56/push-esi
15869     # esi = stmts
15870     8b/-> *(ebp+8) 6/r32/esi
15871     {
15872 $check-mu-stmt-list:loop:
15873       81 7/subop/compare %esi 0/imm32
15874       0f 84/jump-if-= break/disp32
15875       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
15876       (lookup *esi *(esi+4))  # List-value List-value => eax
15877       {
15878 $check-mu-stmt-list:check-for-block:
15879         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
15880         75/jump-if-!= break/disp8
15881 $check-mu-stmt-list:block:
15882         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15883         eb/jump $check-mu-stmt-list:continue/disp8
15884       }
15885       {
15886 $check-mu-stmt-list:check-for-stmt1:
15887         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
15888         0f 85/jump-if-!= break/disp32
15889 $check-mu-stmt-list:stmt1:
15890         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15891         eb/jump $check-mu-stmt-list:continue/disp8
15892       }
15893       {
15894 $check-mu-stmt-list:check-for-reg-var-def:
15895         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
15896         0f 85/jump-if-!= break/disp32
15897 $check-mu-stmt-list:reg-var-def:
15898         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15899         eb/jump $check-mu-stmt-list:continue/disp8
15900       }
15901 $check-mu-stmt-list:continue:
15902       # TODO: raise an error on unrecognized Stmt-tag
15903       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
15904       89/<- %esi 0/r32/eax
15905       e9/jump loop/disp32
15906     }
15907 $check-mu-stmt-list:end:
15908     # . restore registers
15909     5e/pop-to-esi
15910     58/pop-to-eax
15911     # . epilogue
15912     89/<- %esp 5/r32/ebp
15913     5d/pop-to-ebp
15914     c3/return
15915 
15916 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15917     # . prologue
15918     55/push-ebp
15919     89/<- %ebp 4/r32/esp
15920     # . save registers
15921     50/push-eax
15922     # - if stmt's operation matches a primitive, check against it
15923     (has-primitive-name? *(ebp+8))  # => eax
15924     3d/compare-eax-and 0/imm32/false
15925     {
15926       74/jump-if-= break/disp8
15927       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15928       e9/jump $check-mu-stmt:end/disp32
15929     }
15930     # - otherwise find a function to check against
15931     # var f/eax: (addr function) = lookup(*Program->functions)
15932     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15933     (find-matching-function %eax *(ebp+8))  # => eax
15934     3d/compare-eax-and 0/imm32
15935     {
15936       74/jump-if-= break/disp8
15937       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15938       eb/jump $check-mu-stmt:end/disp8
15939     }
15940     # var f/eax: (addr function) = lookup(*Program->signatures)
15941     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
15942     (find-matching-function %eax *(ebp+8))  # => eax
15943     3d/compare-eax-and 0/imm32
15944     {
15945       74/jump-if-= break/disp8
15946       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15947       eb/jump $check-mu-stmt:end/disp8
15948     }
15949     # - otherwise abort
15950     e9/jump $check-mu-stmt:unknown-call/disp32
15951 $check-mu-stmt:end:
15952     # . restore registers
15953     58/pop-to-eax
15954     # . epilogue
15955     89/<- %esp 5/r32/ebp
15956     5d/pop-to-ebp
15957     c3/return
15958 
15959 $check-mu-stmt:unknown-call:
15960     (write-buffered *(ebp+0x10) "unknown function '")
15961     8b/-> *(ebp+8) 0/r32/eax
15962     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
15963     (write-buffered *(ebp+0x10) %eax)
15964     (write-buffered *(ebp+0x10) "'\n")
15965     (flush *(ebp+0x10))
15966     (stop *(ebp+0x14) 1)
15967     # never gets here
15968 
15969 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
15970     # . prologue
15971     55/push-ebp
15972     89/<- %ebp 4/r32/esp
15973     # . save registers
15974     51/push-ecx
15975     56/push-esi
15976     # var name/esi: (addr array byte) = lookup(stmt->operation)
15977     8b/-> *(ebp+8) 6/r32/esi
15978     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
15979     89/<- %esi 0/r32/eax
15980     # if (name == "return") return true
15981     (string-equal? %esi "return")  # => eax
15982     3d/compare-eax-and 0/imm32/false
15983     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15984     # if (name == "get") return true
15985     (string-equal? %esi "get")  # => eax
15986     3d/compare-eax-and 0/imm32/false
15987     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15988     # if (name == "index") return true
15989     (string-equal? %esi "index")  # => eax
15990     3d/compare-eax-and 0/imm32/false
15991     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15992     # if (name == "length") return true
15993     (string-equal? %esi "length")  # => eax
15994     3d/compare-eax-and 0/imm32/false
15995     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15996     # if (name == "compute-offset") return true
15997     (string-equal? %esi "compute-offset")  # => eax
15998     3d/compare-eax-and 0/imm32/false
15999     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16000     # if (name == "copy-object") return true
16001     (string-equal? %esi "copy-object")  # => eax
16002     3d/compare-eax-and 0/imm32/false
16003     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16004     # if (name == "allocate") return true
16005     (string-equal? %esi "allocate")  # => eax
16006     3d/compare-eax-and 0/imm32/false
16007     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16008     # if (name == "populate") return true
16009     (string-equal? %esi "populate")  # => eax
16010     3d/compare-eax-and 0/imm32/false
16011     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16012     # if (name == "populate-stream") return true
16013     (string-equal? %esi "populate-stream")  # => eax
16014     3d/compare-eax-and 0/imm32/false
16015     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16016     # if (name == "read-from-stream") return true
16017     (string-equal? %esi "read-from-stream")  # => eax
16018     3d/compare-eax-and 0/imm32/false
16019     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16020     # if (name == "write-to-stream") return true
16021     (string-equal? %esi "write-to-stream")  # => eax
16022     3d/compare-eax-and 0/imm32/false
16023     0f 85/jump-if-!= $has-primitive-name?:end/disp32
16024     # var curr/ecx: (addr primitive) = Primitives
16025     b9/copy-to-ecx Primitives/imm32
16026     {
16027 $has-primitive-name?:loop:
16028       # if (curr == null) break
16029       81 7/subop/compare %ecx 0/imm32
16030       74/jump-if-= break/disp8
16031       # if (primitive->name == name) return true
16032       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
16033 #?       (write-buffered Stderr %eax)
16034 #?       (write-buffered Stderr Newline)
16035 #?       (flush Stderr)
16036       (string-equal? %esi %eax)  # => eax
16037       3d/compare-eax-and 0/imm32/false
16038       75/jump-if-!= $has-primitive-name?:end/disp8
16039 $has-primitive-name?:next-primitive:
16040       # curr = curr->next
16041       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
16042       89/<- %ecx 0/r32/eax
16043       #
16044       e9/jump loop/disp32
16045     }
16046     # return null
16047     b8/copy-to-eax 0/imm32
16048 $has-primitive-name?:end:
16049     # . restore registers
16050     5e/pop-to-esi
16051     59/pop-to-ecx
16052     # . epilogue
16053     89/<- %esp 5/r32/ebp
16054     5d/pop-to-ebp
16055     c3/return
16056 
16057 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16058     # . prologue
16059     55/push-ebp
16060     89/<- %ebp 4/r32/esp
16061     # . save registers
16062     50/push-eax
16063     51/push-ecx
16064     # var op/ecx: (addr array byte) = lookup(stmt->operation)
16065     8b/-> *(ebp+8) 0/r32/eax
16066     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
16067     89/<- %ecx 0/r32/eax
16068     # if (op == "copy") check-mu-copy-stmt
16069     {
16070       (string-equal? %ecx "copy")  # => eax
16071       3d/compare-eax-and 0/imm32/false
16072       74/jump-if-= break/disp8
16073       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16074       e9/jump $check-mu-primitive:end/disp32
16075     }
16076     # if (op == "copy-to") check-mu-copy-to-stmt
16077     {
16078       (string-equal? %ecx "copy-to")  # => eax
16079       3d/compare-eax-and 0/imm32/false
16080       74/jump-if-= break/disp8
16081       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16082       e9/jump $check-mu-primitive:end/disp32
16083     }
16084     # if (op == "compare") check-mu-compare-stmt
16085     {
16086       (string-equal? %ecx "compare")  # => eax
16087       3d/compare-eax-and 0/imm32/false
16088       74/jump-if-= break/disp8
16089       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16090       e9/jump $check-mu-primitive:end/disp32
16091     }
16092     # if (op == "address") check-mu-address-stmt
16093     {
16094       (string-equal? %ecx "address")  # => eax
16095       3d/compare-eax-and 0/imm32/false
16096       74/jump-if-= break/disp8
16097       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16098       e9/jump $check-mu-primitive:end/disp32
16099     }
16100     # if (op == "return") check-mu-return-stmt
16101     {
16102       (string-equal? %ecx "return")  # => eax
16103       3d/compare-eax-and 0/imm32/false
16104       74/jump-if-= break/disp8
16105       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16106       e9/jump $check-mu-primitive:end/disp32
16107     }
16108     # if (op == "get") check-mu-get-stmt
16109     {
16110       (string-equal? %ecx "get")  # => eax
16111       3d/compare-eax-and 0/imm32/false
16112       74/jump-if-= break/disp8
16113       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16114       e9/jump $check-mu-primitive:end/disp32
16115     }
16116     # if (op == "index") check-mu-index-stmt
16117     {
16118       (string-equal? %ecx "index")  # => eax
16119       3d/compare-eax-and 0/imm32/false
16120       74/jump-if-= break/disp8
16121       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16122       e9/jump $check-mu-primitive:end/disp32
16123     }
16124     # if (op == "length") check-mu-length-stmt
16125     {
16126       (string-equal? %ecx "length")  # => eax
16127       3d/compare-eax-and 0/imm32/false
16128       74/jump-if-= break/disp8
16129       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16130       e9/jump $check-mu-primitive:end/disp32
16131     }
16132     # if (op == "compute-offset") check-mu-compute-offset-stmt
16133     {
16134       (string-equal? %ecx "compute-offset")  # => eax
16135       3d/compare-eax-and 0/imm32/false
16136       74/jump-if-= break/disp8
16137       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16138       e9/jump $check-mu-primitive:end/disp32
16139     }
16140     # if (op == "copy-object") check-mu-copy-object-stmt
16141     {
16142       (string-equal? %ecx "copy-object")  # => eax
16143       3d/compare-eax-and 0/imm32/false
16144       74/jump-if-= break/disp8
16145       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16146       e9/jump $check-mu-primitive:end/disp32
16147     }
16148     # if (op == "allocate") check-mu-allocate-stmt
16149     {
16150       (string-equal? %ecx "allocate")  # => eax
16151       3d/compare-eax-and 0/imm32/false
16152       74/jump-if-= break/disp8
16153       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16154       e9/jump $check-mu-primitive:end/disp32
16155     }
16156     # if (op == "populate") check-mu-populate-stmt
16157     {
16158       (string-equal? %ecx "populate")  # => eax
16159       3d/compare-eax-and 0/imm32/false
16160       74/jump-if-= break/disp8
16161       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16162       e9/jump $check-mu-primitive:end/disp32
16163     }
16164     # if (op == "populate-stream") check-mu-populate-stream-stmt
16165     {
16166       (string-equal? %ecx "populate-stream")  # => eax
16167       3d/compare-eax-and 0/imm32/false
16168       74/jump-if-= break/disp8
16169       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16170       e9/jump $check-mu-primitive:end/disp32
16171     }
16172     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
16173     {
16174       (string-equal? %ecx "read-from-stream")  # => eax
16175       3d/compare-eax-and 0/imm32/false
16176       74/jump-if-= break/disp8
16177       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16178       e9/jump $check-mu-primitive:end/disp32
16179     }
16180     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
16181     {
16182       (string-equal? %ecx "write-to-stream")  # => eax
16183       3d/compare-eax-and 0/imm32/false
16184       74/jump-if-= break/disp8
16185       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16186       e9/jump $check-mu-primitive:end/disp32
16187     }
16188     # if (op == "convert") check-mu-convert-stmt
16189     {
16190       (string-equal? %ecx "convert")  # => eax
16191       3d/compare-eax-and 0/imm32/false
16192       74/jump-if-= break/disp8
16193       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16194       e9/jump $check-mu-primitive:end/disp32
16195     }
16196     # otherwise check-numberlike-stmt
16197     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16198 $check-mu-primitive:end:
16199     # . restore registers
16200     59/pop-to-ecx
16201     58/pop-to-eax
16202     # . epilogue
16203     89/<- %esp 5/r32/ebp
16204     5d/pop-to-ebp
16205     c3/return
16206 
16207 # by default, Mu primitives should only operate on 'number-like' types
16208 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16209     # . prologue
16210     55/push-ebp
16211     89/<- %ebp 4/r32/esp
16212     # . save registers
16213     50/push-eax
16214     51/push-ecx
16215     56/push-esi
16216     # esi = stmt
16217     8b/-> *(ebp+8) 6/r32/esi
16218     # var gas/ecx: int = 2
16219     b9/copy-to-ecx 2/imm32
16220     # - check at most 1 output
16221     # var output/eax: (addr stmt-var) = stmt->outputs
16222     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16223     {
16224       3d/compare-eax-and 0/imm32
16225       74/jump-if-= break/disp8
16226 $check-mu-numberlike-primitive:output:
16227       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16228       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16229       3d/compare-eax-and 0/imm32
16230       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
16231       # check output is in a register
16232       # --gas
16233       49/decrement-ecx
16234     }
16235     # - check first inout
16236     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16237     {
16238       3d/compare-eax-and 0/imm32
16239       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
16240 $check-mu-numberlike-primitive:first-inout:
16241       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16242       # --gas
16243       49/decrement-ecx
16244     }
16245     # - check second inout
16246     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16247     {
16248       3d/compare-eax-and 0/imm32
16249       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
16250 $check-mu-numberlike-primitive:second-inout:
16251       # is a second inout allowed?
16252       81 7/subop/compare %ecx 0/imm32
16253       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
16254 $check-mu-numberlike-primitive:second-inout-permitted:
16255       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
16256     }
16257 $check-mu-numberlike-primitive:third-inout:
16258     # if there's a third arg, raise an error
16259     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
16260     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
16261 $check-mu-numberlike-primitive:end:
16262     # . restore registers
16263     5e/pop-to-esi
16264     59/pop-to-ecx
16265     58/pop-to-eax
16266     # . epilogue
16267     89/<- %esp 5/r32/ebp
16268     5d/pop-to-ebp
16269     c3/return
16270 
16271 $check-mu-numberlike-primitive:error-too-many-inouts:
16272     (write-buffered *(ebp+0x10) "fn ")
16273     8b/-> *(ebp+0xc) 0/r32/eax
16274     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16275     (write-buffered *(ebp+0x10) %eax)
16276     (write-buffered *(ebp+0x10) ": stmt ")
16277     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
16278     (write-buffered *(ebp+0x10) %eax)
16279     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
16280     (flush *(ebp+0x10))
16281     (stop *(ebp+0x14) 1)
16282     # never gets here
16283 
16284 $check-mu-numberlike-primitive:error-too-many-outputs:
16285     (write-buffered *(ebp+0x10) "fn ")
16286     8b/-> *(ebp+0xc) 0/r32/eax
16287     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16288     (write-buffered *(ebp+0x10) %eax)
16289     (write-buffered *(ebp+0x10) ": stmt ")
16290     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
16291     (write-buffered *(ebp+0x10) %eax)
16292     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
16293     (flush *(ebp+0x10))
16294     (stop *(ebp+0x14) 1)
16295     # never gets here
16296 
16297 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16298     # . prologue
16299     55/push-ebp
16300     89/<- %ebp 4/r32/esp
16301     # . save registers
16302     50/push-eax
16303     56/push-esi
16304     # var t/esi: (addr type-tree) = lookup(v->value->type)
16305     8b/-> *(ebp+8) 0/r32/eax
16306     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16307     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16308     89/<- %esi 0/r32/eax
16309 $check-mu-numberlike-arg:check-literal:
16310     # if t is an int, return
16311     (is-simple-mu-type? %esi 0)  # literal => eax
16312     3d/compare-eax-and 0/imm32/false
16313     75/jump-if-!= $check-mu-numberlike-arg:end/disp8
16314 $check-mu-numberlike-arg:check-addr:
16315     # if t is an addr and v is dereferenced, return
16316     {
16317       (is-mu-addr-type? %esi)  # => eax
16318       3d/compare-eax-and 0/imm32/false
16319       74/jump-if-= break/disp8
16320       8b/-> *(ebp+8) 0/r32/eax
16321       8b/-> *(eax+0x10) 0/r32/eax
16322       3d/compare-eax-and 0/imm32/false
16323       75/jump-if-!= $check-mu-numberlike-arg:end/disp8
16324     }
16325 $check-mu-numberlike-arg:output-checks:
16326     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
16327 $check-mu-numberlike-arg:end:
16328     # . restore registers
16329     5e/pop-to-esi
16330     58/pop-to-eax
16331     # . epilogue
16332     89/<- %esp 5/r32/ebp
16333     5d/pop-to-ebp
16334     c3/return
16335 
16336 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16337     # . prologue
16338     55/push-ebp
16339     89/<- %ebp 4/r32/esp
16340     # . save registers
16341     50/push-eax
16342     56/push-esi
16343     # var t/esi: (addr type-tree) = lookup(v->value->type)
16344     8b/-> *(ebp+8) 0/r32/eax
16345     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16346     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16347     89/<- %esi 0/r32/eax
16348 $check-mu-numberlike-output:check-int:
16349     # if t is an int, return
16350     (is-simple-mu-type? %esi 1)  # int => eax
16351     3d/compare-eax-and 0/imm32/false
16352     0f 85/jump-if-!= $check-mu-numberlike-output:end/disp32
16353 $check-mu-numberlike-output:check-float:
16354     # if t is a float, return
16355     (is-simple-mu-type? %esi 0xf)  # float => eax
16356     3d/compare-eax-and 0/imm32/false
16357     75/jump-if-!= $check-mu-numberlike-output:end/disp8
16358 $check-mu-numberlike-output:check-boolean:
16359     # if t is a boolean, return
16360     (is-simple-mu-type? %esi 5)  # boolean => eax
16361     3d/compare-eax-and 0/imm32/false
16362     75/jump-if-!= $check-mu-numberlike-output:end/disp8
16363 $check-mu-numberlike-output:check-byte:
16364     # if t is a byte, return
16365     (is-simple-mu-type? %esi 8)  # byte => eax
16366     3d/compare-eax-and 0/imm32/false
16367     75/jump-if-!= $check-mu-numberlike-output:end/disp8
16368 $check-mu-numberlike-output:check-code-point:
16369     # if t is a code-point, return
16370     (is-simple-mu-type? %esi 0xd)  # code-point => eax
16371     3d/compare-eax-and 0/imm32/false
16372     75/jump-if-!= $check-mu-numberlike-output:end/disp8
16373 $check-mu-numberlike-output:check-grapheme:
16374     # if t is a grapheme, return
16375     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
16376     3d/compare-eax-and 0/imm32/false
16377     75/jump-if-!= $check-mu-numberlike-output:end/disp8
16378     e9/jump $check-mu-numberlike-output:fail/disp32
16379 $check-mu-numberlike-output:end:
16380     # . restore registers
16381     5e/pop-to-esi
16382     58/pop-to-eax
16383     # . epilogue
16384     89/<- %esp 5/r32/ebp
16385     5d/pop-to-ebp
16386     c3/return
16387 
16388 $check-mu-numberlike-output:fail:
16389     # otherwise raise an error
16390     (write-buffered *(ebp+0x14) "fn ")
16391     8b/-> *(ebp+0x10) 0/r32/eax
16392     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16393     (write-buffered *(ebp+0x14) %eax)
16394     (write-buffered *(ebp+0x14) ": stmt ")
16395     8b/-> *(ebp+0xc) 0/r32/eax
16396     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
16397     (write-buffered *(ebp+0x14) %eax)
16398     (write-buffered *(ebp+0x14) ": only non-addr scalar args permitted\n")
16399     (flush *(ebp+0x14))
16400     (stop *(ebp+0x18) 1)
16401     # never gets here
16402 
16403 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16404     # . prologue
16405     55/push-ebp
16406     89/<- %ebp 4/r32/esp
16407     # . save registers
16408 $check-mu-copy-stmt:end:
16409     # . restore registers
16410     # . epilogue
16411     89/<- %esp 5/r32/ebp
16412     5d/pop-to-ebp
16413     c3/return
16414 
16415 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16416     # . prologue
16417     55/push-ebp
16418     89/<- %ebp 4/r32/esp
16419     # . save registers
16420 $check-mu-copy-to-stmt:end:
16421     # . restore registers
16422     # . epilogue
16423     89/<- %esp 5/r32/ebp
16424     5d/pop-to-ebp
16425     c3/return
16426 
16427 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16428     # . prologue
16429     55/push-ebp
16430     89/<- %ebp 4/r32/esp
16431     # . save registers
16432 $check-mu-compare-stmt:end:
16433     # . restore registers
16434     # . epilogue
16435     89/<- %esp 5/r32/ebp
16436     5d/pop-to-ebp
16437     c3/return
16438 
16439 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16440     # . prologue
16441     55/push-ebp
16442     89/<- %ebp 4/r32/esp
16443     # . save registers
16444 $check-mu-address-stmt:end:
16445     # . restore registers
16446     # . epilogue
16447     89/<- %esp 5/r32/ebp
16448     5d/pop-to-ebp
16449     c3/return
16450 
16451 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16452     # . prologue
16453     55/push-ebp
16454     89/<- %ebp 4/r32/esp
16455     # . save registers
16456     50/push-eax
16457     51/push-ecx
16458     52/push-edx
16459     53/push-ebx
16460     56/push-esi
16461     57/push-edi
16462     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
16463     81 5/subop/subtract %esp 0x60/imm32
16464     68/push 0x60/imm32/size
16465     68/push 0/imm32/read
16466     68/push 0/imm32/write
16467     89/<- %edx 4/r32/esp
16468     # var template/esi: (addr list var) = fn->outputs
16469     8b/-> *(ebp+0xc) 0/r32/eax
16470     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
16471     89/<- %esi 0/r32/eax
16472     # var curr-template/ebx: (addr list var) = fn->outputs
16473     89/<- %ebx 0/r32/eax
16474     # var curr/edi: (addr stmt-var) = stmt->inouts
16475     8b/-> *(ebp+8) 0/r32/eax
16476     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16477     89/<- %edi 0/r32/eax
16478     {
16479       # if template is null, break
16480       81 7/subop/compare %ebx 0/imm32
16481       0f 84/jump-if-= break/disp32
16482       # if curr is null, abort
16483       81 7/subop/compare %edi 0/imm32
16484       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
16485       # var template-type/ecx: (addr type-tree) = template->value->type
16486       (lookup *ebx *(ebx+4))  # List-value List-value => eax
16487       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16488       89/<- %ecx 0/r32/eax
16489       # var curr-type/eax: (addr type-tree) = curr->value->type
16490       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
16491       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16492       # if (curr->is-deref?) curr-type = payload of curr-type
16493       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
16494       {
16495         74/jump-if-= break/disp8
16496         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16497         # if t->right is null, t = t->left
16498         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
16499         75/jump-if-!= break/disp8
16500         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16501       }
16502       # if (curr-type != template-type) abort
16503       (type-match? %ecx %eax %edx)  # => eax
16504       3d/compare-eax-and 0/imm32/false
16505       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
16506       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
16507       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
16508       3d/compare-eax-and 0/imm32/false
16509       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
16510       # template = template->next
16511       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
16512       89/<- %ebx 0/r32/eax
16513       # curr = curr->next
16514       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
16515       89/<- %edi 0/r32/eax
16516       #
16517       e9/jump loop/disp32
16518     }
16519     # if curr is not null, abort
16520     81 7/subop/compare %edi 0/imm32
16521     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
16522 $check-mu-return-stmt:end:
16523     # . reclaim locals
16524     81 0/subop/add %esp 0x6c/imm32
16525     # . restore registers
16526     5f/pop-to-edi
16527     5e/pop-to-esi
16528     5b/pop-to-ebx
16529     5a/pop-to-edx
16530     59/pop-to-ecx
16531     58/pop-to-eax
16532     # . epilogue
16533     89/<- %esp 5/r32/ebp
16534     5d/pop-to-ebp
16535     c3/return
16536 
16537 $check-mu-return-stmt:error1:
16538     (write-buffered *(ebp+0x10) "fn ")
16539     8b/-> *(ebp+0xc) 0/r32/eax
16540     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16541     (write-buffered *(ebp+0x10) %eax)
16542     (write-buffered *(ebp+0x10) ": return: '")
16543     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
16544     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16545     (write-buffered *(ebp+0x10) %eax)
16546     (write-buffered *(ebp+0x10) "' has the wrong type\n")
16547     (flush *(ebp+0x10))
16548     (stop *(ebp+0x14) 1)
16549     # never gets here
16550 
16551 $check-mu-return-stmt:error2:
16552     (write-buffered *(ebp+0x10) "fn ")
16553     8b/-> *(ebp+0xc) 0/r32/eax
16554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16555     (write-buffered *(ebp+0x10) %eax)
16556     (write-buffered *(ebp+0x10) ": return: '")
16557     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
16558     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16559     (write-buffered *(ebp+0x10) %eax)
16560     (write-buffered *(ebp+0x10) "' is no longer available\n")
16561     (flush *(ebp+0x10))
16562     (stop *(ebp+0x14) 1)
16563     # never gets here
16564 
16565 $check-mu-return-stmt:error-too-few-inouts:
16566     (write-buffered *(ebp+0x10) "fn ")
16567     8b/-> *(ebp+0xc) 0/r32/eax
16568     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16569     (write-buffered *(ebp+0x10) %eax)
16570     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
16571     (flush *(ebp+0x10))
16572     (stop *(ebp+0x14) 1)
16573     # never gets here
16574 
16575 $check-mu-return-stmt:error-too-many-inouts:
16576     (write-buffered *(ebp+0x10) "fn ")
16577     8b/-> *(ebp+0xc) 0/r32/eax
16578     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16579     (write-buffered *(ebp+0x10) %eax)
16580     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
16581     (flush *(ebp+0x10))
16582     (stop *(ebp+0x14) 1)
16583     # never gets here
16584 
16585 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16586     # . prologue
16587     55/push-ebp
16588     89/<- %ebp 4/r32/esp
16589     # . save registers
16590     50/push-eax
16591     51/push-ecx
16592     56/push-esi
16593     # var table/esi: (addr table (handle array byte) int 8)
16594     81 5/subop/subtract %esp 0x60/imm32
16595     68/push 0x60/imm32/size
16596     68/push 0/imm32/read
16597     68/push 0/imm32/write
16598     89/<- %esi 4/r32/esp
16599     # var curr/ecx: (addr list var) = outputs
16600     8b/-> *(ebp+8) 1/r32/ecx
16601     {
16602       # if (curr == 0) break
16603       81 7/subop/compare %ecx 0/imm32
16604       0f 84/jump-if-= break/disp32
16605       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
16606       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16607       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16608       # if reg exists in table, abort
16609       (maybe-get %esi %eax 0xc)  # => eax
16610       3d/compare-eax-and 0/imm32
16611       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
16612       # insert reg in table
16613       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16614       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16615       (get-or-insert %esi %eax 0xc Heap)
16616       # curr = curr->next
16617       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16618       89/<- %ecx 0/r32/eax
16619       e9/jump loop/disp32
16620     }
16621 $check-all-unique-registers:end:
16622     # . reclaim locals
16623     81 0/subop/add %esp 0x6c/imm32
16624     # . restore registers
16625     5e/pop-to-esi
16626     59/pop-to-ecx
16627     58/pop-to-eax
16628     # . epilogue
16629     89/<- %esp 5/r32/ebp
16630     5d/pop-to-ebp
16631     c3/return
16632 
16633 $check-all-unique-registers:abort:
16634     (write-buffered *(ebp+0x10) "fn ")
16635     8b/-> *(ebp+0xc) 0/r32/eax
16636     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16637     (write-buffered *(ebp+0x10) %eax)
16638     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
16639     (flush *(ebp+0x10))
16640     (stop *(ebp+0x14) 1)
16641     # never gets here
16642 
16643 # return false if s's register is not between start (inclusive) and end (exclusive)
16644 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
16645 # otherwise return true
16646 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
16647     # . prologue
16648     55/push-ebp
16649     89/<- %ebp 4/r32/esp
16650     # . save registers
16651     51/push-ecx
16652     52/push-edx
16653     53/push-ebx
16654     56/push-esi
16655     57/push-edi
16656     # var target/ebx: (addr array byte) = s->value->register
16657     8b/-> *(ebp+8) 0/r32/eax
16658     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16659     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16660 #?     (write-buffered Stderr "AA: ")
16661 #?     (write-buffered Stderr %eax)
16662 #?     (write-buffered Stderr Newline)
16663 #?     (flush Stderr)
16664     # if (var->register == 0) return false
16665     3d/compare-eax-and 0/imm32
16666     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
16667     89/<- %ebx 0/r32/eax
16668     # var curr/ecx: (addr list var) = start
16669     8b/-> *(ebp+0xc) 1/r32/ecx
16670     # edx = end
16671     8b/-> *(ebp+0x10) 2/r32/edx
16672     {
16673       # if (curr == 0) break
16674       81 7/subop/compare %edi 0/imm32
16675       0f 84/jump-if-= break/disp32
16676       # if (curr == end) break
16677       39/compare %ecx 2/r32/edx
16678       0f 84/jump-if-= break/disp32
16679       # var curr-reg/eax: (addr array byte) = curr->value->register
16680       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16681       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16682       # if (curr-reg == 0) continue
16683       3d/compare-eax-and 0/imm32
16684       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
16685       # if (curr-reg == target) check for conflict
16686       (string-equal? %eax %ebx)  # => eax
16687       3d/compare-eax-and 0/imm32/false
16688       {
16689         74/jump-if-= break/disp8
16690 #?         (write-buffered Stderr "conflict?\n")
16691 #?         (flush Stderr)
16692         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
16693         8b/-> *(ebp+0x14) 0/r32/eax
16694         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16695         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
16696         eb/jump $register-within-list-with-conflict?:end/disp8
16697       }
16698 $register-within-list-with-conflict?:continue:
16699       # curr = curr->next
16700       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16701       89/<- %ecx 0/r32/eax
16702       e9/jump loop/disp32
16703     }
16704     # return false
16705     b8/copy-to-eax 0/imm32/false
16706 $register-within-list-with-conflict?:end:
16707     # . restore registers
16708     5f/pop-to-edi
16709     5e/pop-to-esi
16710     5b/pop-to-ebx
16711     5a/pop-to-edx
16712     59/pop-to-ecx
16713     # . epilogue
16714     89/<- %esp 5/r32/ebp
16715     5d/pop-to-ebp
16716     c3/return
16717 
16718 # At the first occurrence of register 'reg' in fn-outputs,
16719 # check if the corresponding element of return-inouts has a different register.
16720 # This hacky helper is intended to be called in one specific place. Don't
16721 # reuse it as is.
16722 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
16723     # . prologue
16724     55/push-ebp
16725     89/<- %ebp 4/r32/esp
16726     # . save registers
16727     51/push-ecx
16728     52/push-edx
16729     53/push-ebx
16730     56/push-esi
16731     57/push-edi
16732 #?     (write-buffered Stderr "BB: ")
16733 #?     (write-buffered Stderr *(ebp+8))
16734 #?     (write-buffered Stderr Newline)
16735 #?     (flush Stderr)
16736     # var curr-output/edi: (addr list var) = fn-outputs
16737     8b/-> *(ebp+0x10) 7/r32/edi
16738     # var curr-inout/esi: (addr stmt-var) = return-inouts
16739     8b/-> *(ebp+0xc) 6/r32/esi
16740     {
16741       # if (curr-output == 0) abort
16742       81 7/subop/compare %edi 0/imm32
16743       0f 84/jump-if-= break/disp32
16744       # if (curr-output->value->register != reg) continue
16745       (lookup *edi *(edi+4))  # List-value List-value => eax
16746       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16747       (string-equal? %eax *(ebp+8))  # => eax
16748       3d/compare-eax-and 0/imm32/false
16749       0f 84/jump-if= $register-conflict?:continue/disp32
16750 #?       (write-buffered Stderr "rescan\n")
16751 #?       (flush Stderr)
16752       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
16753       (lookup *esi *(esi+4))  # List-value List-value => eax
16754       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16755       # if (curr-reg == 0) return true
16756       3d/compare-eax-and 0/imm32
16757       {
16758         75/jump-if-!= break/disp8
16759 #?         (write-buffered Stderr "no register\n")
16760 #?         (flush Stderr)
16761         b8/copy-to-eax 1/imm32/true
16762         e9/jump $register-conflict?:end/disp32
16763       }
16764       # return (curr-reg != reg)
16765       (string-equal? %eax *(ebp+8))  # => eax
16766       3d/compare-eax-and 0/imm32/false
16767       0f 94/set-if-= %al
16768 #?       (write-buffered Stderr "final: ")
16769 #?       (write-int32-hex-buffered Stderr %eax)
16770 #?       (write-buffered Stderr Newline)
16771 #?       (flush Stderr)
16772       eb/jump $register-conflict?:end/disp8
16773 $register-conflict?:continue:
16774       # curr-output = curr-output->next
16775       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
16776       89/<- %edi 0/r32/eax
16777       # curr-inout = curr-inout->next
16778       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
16779       89/<- %esi 0/r32/eax
16780       e9/jump loop/disp32
16781     }
16782     # should never get here
16783     (write-buffered Stderr "register-conflict? misused\n")
16784     (flush Stderr)
16785     e8/call syscall_exit/disp32
16786 $register-conflict?:end:
16787     # . restore registers
16788     5f/pop-to-edi
16789     5e/pop-to-esi
16790     5b/pop-to-ebx
16791     5a/pop-to-edx
16792     59/pop-to-ecx
16793     # . epilogue
16794     89/<- %esp 5/r32/ebp
16795     5d/pop-to-ebp
16796     c3/return
16797 
16798 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16799     # . prologue
16800     55/push-ebp
16801     89/<- %ebp 4/r32/esp
16802     # . save registers
16803     50/push-eax
16804     51/push-ecx
16805     # var curr/ecx: (addr list stmt) = block->stmts
16806     8b/-> *(ebp+8) 0/r32/eax
16807     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
16808     3d/compare-eax-and 0/imm32
16809     74/jump-if-= $check-final-stmt-is-return:end/disp8
16810     89/<- %ecx 0/r32/eax
16811     {
16812       # if curr->next == 0, break
16813       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16814       3d/compare-eax-and 0/imm32
16815       74/jump-if-= break/disp8
16816       # curr = curr->next
16817       89/<- %ecx 0/r32/eax
16818       e9/jump loop/disp32
16819     }
16820 $check-final-stmt-is-return:check-tag:
16821     # if curr->value->tag != Stmt1, abort
16822     (lookup *ecx *(ecx+4))  # List-value List-value => eax
16823     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
16824     75/jump-if-!= $check-final-stmt-is-return:error/disp8
16825 $check-final-stmt-is-return:check-operation:
16826     # if curr->operation != "return", abort
16827     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
16828     (string-equal? %eax "return")
16829     3d/compare-eax-and 0/imm32/false
16830     74/jump-if-= $check-final-stmt-is-return:error/disp8
16831 $check-final-stmt-is-return:end:
16832     # . restore registers
16833     59/pop-to-ecx
16834     58/pop-to-eax
16835     # . epilogue
16836     89/<- %esp 5/r32/ebp
16837     5d/pop-to-ebp
16838     c3/return
16839 
16840 $check-final-stmt-is-return:error:
16841     (write-buffered *(ebp+0x10) "fn ")
16842     8b/-> *(ebp+0xc) 0/r32/eax
16843     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16844     (write-buffered *(ebp+0x10) %eax)
16845     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
16846     (flush *(ebp+0x10))
16847     (stop *(ebp+0x14) 1)
16848     # never gets here
16849 
16850 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16851     # . prologue
16852     55/push-ebp
16853     89/<- %ebp 4/r32/esp
16854     # . save registers
16855     50/push-eax
16856     51/push-ecx
16857     # var curr/ecx: (addr list stmt) = block->stmts
16858     8b/-> *(ebp+8) 0/r32/eax
16859     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
16860     3d/compare-eax-and 0/imm32
16861     0f 84/jump-if-= $check-no-breaks:end/disp32
16862     89/<- %ecx 0/r32/eax
16863     {
16864       # if curr->next == 0, break
16865       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16866       3d/compare-eax-and 0/imm32
16867       74/jump-if-= break/disp8
16868       # if curr->value->tag != Stmt1, continue
16869       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16870       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
16871       75/jump-if-!= $check-no-breaks:continue/disp8
16872       # if curr->value->operation starts with "break", abort
16873       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
16874       (string-starts-with? %eax "break")  # => eax
16875       3d/compare-eax-and 0/imm32/false
16876       75/jump-if-!= $check-no-breaks:error/disp8
16877 $check-no-breaks:continue:
16878       # curr = curr->next
16879       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16880       89/<- %ecx 0/r32/eax
16881       e9/jump loop/disp32
16882     }
16883 $check-no-breaks:end:
16884     # . restore registers
16885     59/pop-to-ecx
16886     58/pop-to-eax
16887     # . epilogue
16888     89/<- %esp 5/r32/ebp
16889     5d/pop-to-ebp
16890     c3/return
16891 
16892 $check-no-breaks:error:
16893     (write-buffered *(ebp+0x10) "fn ")
16894     8b/-> *(ebp+0xc) 0/r32/eax
16895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16896     (write-buffered *(ebp+0x10) %eax)
16897     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
16898     (flush *(ebp+0x10))
16899     (stop *(ebp+0x14) 1)
16900     # never gets here
16901 
16902 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16903     # . prologue
16904     55/push-ebp
16905     89/<- %ebp 4/r32/esp
16906     # . save registers
16907     50/push-eax
16908     51/push-ecx
16909     52/push-edx
16910     53/push-ebx
16911     56/push-esi
16912     57/push-edi
16913     # esi = stmt
16914     8b/-> *(ebp+8) 6/r32/esi
16915     # - check for 0 inouts
16916     # var base/ecx: (addr var) = stmt->inouts->value
16917     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16918     3d/compare-eax-and 0/imm32/false
16919     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
16920     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16921     89/<- %ecx 0/r32/eax
16922 $check-mu-get-stmt:check-base:
16923     # - check base type
16924     # if it's an 'addr', check that it's in a register
16925     # var base-type/ebx: (addr type-tree) = lookup(base->type)
16926     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16927     89/<- %ebx 0/r32/eax
16928     {
16929       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
16930       0f 85/jump-if-!= break/disp32
16931 $check-mu-get-stmt:base-is-compound:
16932       # if (type->left != addr) break
16933       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16934       (is-simple-mu-type? %eax 2)  # addr => eax
16935       3d/compare-eax-and 0/imm32/false
16936       74/jump-if-= break/disp8
16937 $check-mu-get-stmt:base-is-addr:
16938       # now check for register
16939       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
16940       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
16941 $check-mu-get-stmt:base-is-addr-in-register:
16942       # type->left is now an addr; skip it
16943       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16944       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
16945       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
16946 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
16947       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16948       89/<- %ebx 0/r32/eax
16949     }
16950 $check-mu-get-stmt:check-base-typeinfo:
16951     # ensure type is a container
16952     # var base-type-id/ebx: type-id = base-type->value
16953     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
16954     (is-container? %ebx)  # => eax
16955     3d/compare-eax-and 0/imm32/false
16956     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
16957     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
16958     # . var container/ecx: (handle typeinfo)
16959     68/push 0/imm32
16960     68/push 0/imm32
16961     89/<- %ecx 4/r32/esp
16962     # .
16963     (find-typeinfo %ebx %ecx)
16964     (lookup *ecx *(ecx+4))  # => eax
16965     # . reclaim container
16966     81 0/subop/add %esp 8/imm32
16967     # .
16968     89/<- %edx 0/r32/eax
16969     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
16970     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16971     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16972     89/<- %ecx 0/r32/eax
16973     # - check for 1 inout
16974     3d/compare-eax-and 0/imm32/false
16975     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
16976     # var offset/ecx: (addr var) = lookup(offset->value)
16977     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
16978     89/<- %ecx 0/r32/eax
16979     # - check for valid field
16980     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
16981     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
16982     # - check for too many inouts
16983     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16984     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16985     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16986     3d/compare-eax-and 0/imm32/false
16987     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
16988     # var output/edi: (addr var) = stmt->outputs->value
16989     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16990     # - check for 0 outputs
16991     3d/compare-eax-and 0/imm32/false
16992     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
16993     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16994     89/<- %edi 0/r32/eax
16995 $check-mu-get-stmt:check-output-type:
16996     # - check output type
16997     # must be in register
16998     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
16999     3d/compare-eax-and 0/imm32
17000     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
17001     # must have a non-atomic type
17002     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17003     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17004     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
17005     # type must start with (addr ...)
17006     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17007     (is-simple-mu-type? %eax 2)  # => eax
17008     3d/compare-eax-and 0/imm32/false
17009     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
17010 $check-mu-get-stmt:check-output-type-match:
17011     # payload of addr type must match 'type' definition
17012     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17013     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17014     # if (payload->right == null) payload = payload->left
17015     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
17016     {
17017       75/jump-if-!= break/disp8
17018       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17019     }
17020     89/<- %edi 0/r32/eax
17021     # . var output-name/ecx: (addr array byte)
17022     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17023     89/<- %ecx 0/r32/eax
17024     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
17025     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
17026     (get %eax %ecx 0x10)  # => eax
17027     # .
17028     (lookup *eax *(eax+4))  # => eax
17029     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
17030     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17031     # .
17032     (type-equal? %edi %eax)  # => eax
17033     3d/compare-eax-and 0/imm32/false
17034     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
17035     # - check for too many outputs
17036     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17037     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17038     3d/compare-eax-and 0/imm32/false
17039     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
17040 $check-mu-get-stmt:end:
17041     # . restore registers
17042     5f/pop-to-edi
17043     5e/pop-to-esi
17044     5b/pop-to-ebx
17045     5a/pop-to-edx
17046     59/pop-to-ecx
17047     58/pop-to-eax
17048     # . epilogue
17049     89/<- %esp 5/r32/ebp
17050     5d/pop-to-ebp
17051     c3/return
17052 
17053 $check-mu-get-stmt:error-too-few-inouts:
17054     (write-buffered *(ebp+0x10) "fn ")
17055     8b/-> *(ebp+0xc) 0/r32/eax
17056     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17057     (write-buffered *(ebp+0x10) %eax)
17058     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
17059     (flush *(ebp+0x10))
17060     (stop *(ebp+0x14) 1)
17061     # never gets here
17062 
17063 $check-mu-get-stmt:error-too-many-inouts:
17064     (write-buffered *(ebp+0x10) "fn ")
17065     8b/-> *(ebp+0xc) 0/r32/eax
17066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17067     (write-buffered *(ebp+0x10) %eax)
17068     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
17069     (flush *(ebp+0x10))
17070     (stop *(ebp+0x14) 1)
17071     # never gets here
17072 
17073 $check-mu-get-stmt:error-too-few-outputs:
17074     (write-buffered *(ebp+0x10) "fn ")
17075     8b/-> *(ebp+0xc) 0/r32/eax
17076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17077     (write-buffered *(ebp+0x10) %eax)
17078     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
17079     (flush *(ebp+0x10))
17080     (stop *(ebp+0x14) 1)
17081     # never gets here
17082 
17083 $check-mu-get-stmt:error-too-many-outputs:
17084     (write-buffered *(ebp+0x10) "fn ")
17085     8b/-> *(ebp+0xc) 0/r32/eax
17086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17087     (write-buffered *(ebp+0x10) %eax)
17088     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
17089     (flush *(ebp+0x10))
17090     (stop *(ebp+0x14) 1)
17091     # never gets here
17092 
17093 $check-mu-get-stmt:error-bad-base:
17094     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
17095     (write-buffered *(ebp+0x10) "fn ")
17096     8b/-> *(ebp+0xc) 0/r32/eax
17097     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17098     (write-buffered *(ebp+0x10) %eax)
17099     (write-buffered *(ebp+0x10) ": stmt get: var '")
17100     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17101     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17102     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17103     (write-buffered *(ebp+0x10) %eax)
17104     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
17105     (flush *(ebp+0x10))
17106     (stop *(ebp+0x14) 1)
17107     # never gets here
17108 
17109 $check-mu-get-stmt:error-base-type-addr-but-not-register:
17110     (write-buffered *(ebp+0x10) "fn ")
17111     8b/-> *(ebp+0xc) 0/r32/eax
17112     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17113     (write-buffered *(ebp+0x10) %eax)
17114     (write-buffered *(ebp+0x10) ": stmt get: var '")
17115     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17116     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17117     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17118     (write-buffered *(ebp+0x10) %eax)
17119     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
17120     (flush *(ebp+0x10))
17121     (stop *(ebp+0x14) 1)
17122     # never gets here
17123 
17124 $check-mu-get-stmt:error-bad-field:
17125     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
17126     (write-buffered *(ebp+0x10) "fn ")
17127     8b/-> *(ebp+0xc) 0/r32/eax
17128     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17129     (write-buffered *(ebp+0x10) %eax)
17130     (write-buffered *(ebp+0x10) ": stmt get: type '")
17131     # . write(Type-id->data[tmp])
17132     bf/copy-to-edi Type-id/imm32
17133     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
17134     # .
17135     (write-buffered *(ebp+0x10) "' has no member called '")
17136     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17137     (write-buffered *(ebp+0x10) %eax)
17138     (write-buffered *(ebp+0x10) "'\n")
17139     (flush *(ebp+0x10))
17140     (stop *(ebp+0x14) 1)
17141     # never gets here
17142 
17143 $check-mu-get-stmt:error-output-not-in-register:
17144     (write-buffered *(ebp+0x10) "fn ")
17145     8b/-> *(ebp+0xc) 0/r32/eax
17146     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17147     (write-buffered *(ebp+0x10) %eax)
17148     (write-buffered *(ebp+0x10) ": stmt get: output '")
17149     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17150     (write-buffered *(ebp+0x10) %eax)
17151     (write-buffered *(ebp+0x10) "' is not in a register\n")
17152     (flush *(ebp+0x10))
17153     (stop *(ebp+0x14) 1)
17154     # never gets here
17155 
17156 $check-mu-get-stmt:error-output-type-not-address:
17157     (write-buffered *(ebp+0x10) "fn ")
17158     8b/-> *(ebp+0xc) 0/r32/eax
17159     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17160     (write-buffered *(ebp+0x10) %eax)
17161     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
17162     (flush *(ebp+0x10))
17163     (stop *(ebp+0x14) 1)
17164     # never gets here
17165 
17166 $check-mu-get-stmt:error-bad-output-type:
17167     (write-buffered *(ebp+0x10) "fn ")
17168     8b/-> *(ebp+0xc) 0/r32/eax
17169     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17170     (write-buffered *(ebp+0x10) %eax)
17171     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
17172     (write-buffered *(ebp+0x10) %ecx)
17173     (write-buffered *(ebp+0x10) "' of type '")
17174     bf/copy-to-edi Type-id/imm32
17175     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
17176     (write-buffered *(ebp+0x10) "'\n")
17177     (flush *(ebp+0x10))
17178     (stop *(ebp+0x14) 1)
17179     # never gets here
17180 
17181 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17182     # . prologue
17183     55/push-ebp
17184     89/<- %ebp 4/r32/esp
17185     # . save registers
17186     50/push-eax
17187     51/push-ecx
17188     52/push-edx
17189     53/push-ebx
17190     56/push-esi
17191     57/push-edi
17192     # esi = stmt
17193     8b/-> *(ebp+8) 6/r32/esi
17194     # - check for 0 inouts
17195     # var base/ecx: (addr var) = stmt->inouts->value
17196     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17197 $check-mu-index-stmt:check-no-inouts:
17198     3d/compare-eax-and 0/imm32
17199     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
17200     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17201     89/<- %ecx 0/r32/eax
17202     # - check base type is either (addr array ...) in register or (array ...) on stack
17203     # var base-type/ebx: (addr type-tree) = lookup(base->type)
17204     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17205     89/<- %ebx 0/r32/eax
17206     # if base-type is an atom, abort with a precise error
17207     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
17208     {
17209       74/jump-if-= break/disp8
17210       (is-simple-mu-type? %ebx 3)  # array => eax
17211       3d/compare-eax-and 0/imm32/false
17212       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
17213       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
17214     }
17215 $check-mu-index-stmt:base-is-compound:
17216     # if type->left not addr or array, abort
17217     {
17218       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17219       (is-simple-mu-type? %eax 2)  # addr => eax
17220       3d/compare-eax-and 0/imm32/false
17221       75/jump-if-!= break/disp8
17222       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17223       (is-simple-mu-type? %eax 3)  # array => eax
17224       3d/compare-eax-and 0/imm32/false
17225       75/jump-if-!= break/disp8
17226       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
17227     }
17228     # if (type->left == addr) ensure type->right->left == array and type->register exists
17229     {
17230       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17231       (is-simple-mu-type? %eax 2)  # addr => eax
17232       3d/compare-eax-and 0/imm32/false
17233       74/jump-if-= break/disp8
17234 $check-mu-index-stmt:base-is-addr:
17235       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17236       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17237       (is-simple-mu-type? %eax 3)  # array => eax
17238       3d/compare-eax-and 0/imm32/false
17239       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
17240 $check-mu-index-stmt:check-base-addr-is-register:
17241       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
17242       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
17243     }
17244     # if (type->left == array) ensure type->register doesn't exist
17245     {
17246       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17247       (is-simple-mu-type? %eax 3)  # array => eax
17248       3d/compare-eax-and 0/imm32/false
17249       74/jump-if-= break/disp8
17250 $check-mu-index-stmt:base-is-array:
17251       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
17252       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
17253     }
17254     # if (base-type->left == addr) base-type = base-type->right
17255     {
17256       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17257       (is-simple-mu-type? %eax 2)  # addr => eax
17258       3d/compare-eax-and 0/imm32/false
17259       74/jump-if-= break/disp8
17260       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17261       89/<- %ebx 0/r32/eax
17262     }
17263     # - check for 1 inout
17264     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
17265     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17266     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17267 $check-mu-index-stmt:check-single-inout:
17268     3d/compare-eax-and 0/imm32
17269     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
17270     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17271     89/<- %ecx 0/r32/eax
17272     # - check index is either a literal or register
17273     # var index-type/edx: (addr type-tree)
17274     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17275     89/<- %edx 0/r32/eax
17276     # if index type is an atom, it must be a literal or int
17277     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
17278     {
17279       74/jump-if-= break/disp8
17280 $check-mu-index-stmt:index-type-is-atom:
17281       (is-simple-mu-type? %edx 0)  # literal => eax
17282       3d/compare-eax-and 0/imm32/false
17283       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
17284       (is-simple-mu-type? %edx 1)  # int => eax
17285       3d/compare-eax-and 0/imm32/false
17286       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
17287       (is-simple-mu-type? %edx 7)  # offset => eax
17288       3d/compare-eax-and 0/imm32/false
17289       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
17290       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
17291     }
17292     # if index type is a non-atom: it must be an offset
17293     {
17294       75/jump-if-!= break/disp8
17295 $check-mu-index-stmt:index-type-is-non-atom:
17296       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17297       (is-simple-mu-type? %eax 7)  # offset => eax
17298       3d/compare-eax-and 0/imm32/false
17299       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
17300     }
17301 $check-mu-index-stmt:index-type-done:
17302     # check index is either a literal or in a register
17303     {
17304       (is-simple-mu-type? %edx 0)  # literal => eax
17305       3d/compare-eax-and 0/imm32/false
17306       75/jump-if-!= break/disp8
17307 $check-mu-index-stmt:check-index-in-register:
17308       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
17309       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
17310     }
17311     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
17312     {
17313       (is-simple-mu-type? %edx 1)  # int => eax
17314       3d/compare-eax-and 0/imm32/false
17315       74/jump-if-= break/disp8
17316 $check-mu-index-stmt:check-index-can-be-int:
17317       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17318       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17319       (array-element-size %eax)  # => eax
17320       3d/compare-eax-and 1/imm32
17321       74/jump-if-= break/disp8
17322       3d/compare-eax-and 2/imm32
17323       74/jump-if-= break/disp8
17324       3d/compare-eax-and 4/imm32
17325       74/jump-if-= break/disp8
17326       3d/compare-eax-and 8/imm32
17327       74/jump-if-= break/disp8
17328       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
17329     }
17330     # - check for too many inouts
17331     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17332     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17333     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17334     3d/compare-eax-and 0/imm32/false
17335     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
17336     # - check for 0 outputs
17337     # var output/edi: (addr var) = stmt->outputs->value
17338     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17339     3d/compare-eax-and 0/imm32/false
17340     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
17341     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17342     89/<- %edi 0/r32/eax
17343     # - check output type
17344     # must have a non-atomic type
17345     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17346     89/<- %edx 0/r32/eax
17347     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
17348     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
17349     # type must start with (addr ...)
17350     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17351     (is-simple-mu-type? %eax 2)  # addr => eax
17352     3d/compare-eax-and 0/imm32/false
17353     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
17354     # if tail(base-type) != tail(output-type) abort
17355     (type-tail %ebx)  # => eax
17356     89/<- %ebx 0/r32/eax
17357     (type-tail %edx)  # => eax
17358     (type-equal? %ebx %eax)  # => eax
17359     3d/compare-eax-and 0/imm32/false
17360     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
17361     # - check for too many outputs
17362     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17363     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17364     3d/compare-eax-and 0/imm32/false
17365     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
17366 $check-mu-index-stmt:end:
17367     # . restore registers
17368     5f/pop-to-edi
17369     5e/pop-to-esi
17370     5b/pop-to-ebx
17371     5a/pop-to-edx
17372     59/pop-to-ecx
17373     58/pop-to-eax
17374     # . epilogue
17375     89/<- %esp 5/r32/ebp
17376     5d/pop-to-ebp
17377     c3/return
17378 
17379 $check-mu-index-stmt:error-base-non-array-type:
17380     (write-buffered *(ebp+0x10) "fn ")
17381     8b/-> *(ebp+0xc) 0/r32/eax
17382     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17383     (write-buffered *(ebp+0x10) %eax)
17384     (write-buffered *(ebp+0x10) ": stmt index: var '")
17385     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17386     (write-buffered *(ebp+0x10) %eax)
17387     (write-buffered *(ebp+0x10) "' is not an array\n")
17388     (flush *(ebp+0x10))
17389     (stop *(ebp+0x14) 1)
17390     # never gets here
17391 
17392 $check-mu-index-stmt:error-base-array-atom-type:
17393     (write-buffered *(ebp+0x10) "fn ")
17394     8b/-> *(ebp+0xc) 0/r32/eax
17395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17396     (write-buffered *(ebp+0x10) %eax)
17397     (write-buffered *(ebp+0x10) ": stmt index: array '")
17398     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17399     (write-buffered *(ebp+0x10) %eax)
17400     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
17401     (flush *(ebp+0x10))
17402     (stop *(ebp+0x14) 1)
17403     # never gets here
17404 
17405 $check-mu-index-stmt:error-base-address-array-type-on-stack:
17406     (write-buffered *(ebp+0x10) "fn ")
17407     8b/-> *(ebp+0xc) 0/r32/eax
17408     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17409     (write-buffered *(ebp+0x10) %eax)
17410     (write-buffered *(ebp+0x10) ": stmt index: var '")
17411     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17412     (write-buffered *(ebp+0x10) %eax)
17413     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
17414     (flush *(ebp+0x10))
17415     (stop *(ebp+0x14) 1)
17416     # never gets here
17417 
17418 $check-mu-index-stmt:error-base-array-type-in-register:
17419     (write-buffered *(ebp+0x10) "fn ")
17420     8b/-> *(ebp+0xc) 0/r32/eax
17421     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17422     (write-buffered *(ebp+0x10) %eax)
17423     (write-buffered *(ebp+0x10) ": stmt index: var '")
17424     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17425     (write-buffered *(ebp+0x10) %eax)
17426     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
17427     (flush *(ebp+0x10))
17428     (stop *(ebp+0x14) 1)
17429     # never gets here
17430 
17431 $check-mu-index-stmt:error-too-few-inouts:
17432     (write-buffered *(ebp+0x10) "fn ")
17433     8b/-> *(ebp+0xc) 0/r32/eax
17434     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17435     (write-buffered *(ebp+0x10) %eax)
17436     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
17437     (flush *(ebp+0x10))
17438     (stop *(ebp+0x14) 1)
17439     # never gets here
17440 
17441 $check-mu-index-stmt:error-invalid-index-type:
17442     (write-buffered *(ebp+0x10) "fn ")
17443     8b/-> *(ebp+0xc) 0/r32/eax
17444     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17445     (write-buffered *(ebp+0x10) %eax)
17446     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
17447     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17448     (write-buffered *(ebp+0x10) %eax)
17449     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
17450     (flush *(ebp+0x10))
17451     (stop *(ebp+0x14) 1)
17452     # never gets here
17453 
17454 $check-mu-index-stmt:error-index-offset-atom-type:
17455     (write-buffered *(ebp+0x10) "fn ")
17456     8b/-> *(ebp+0xc) 0/r32/eax
17457     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17458     (write-buffered *(ebp+0x10) %eax)
17459     (write-buffered *(ebp+0x10) ": stmt index: offset '")
17460     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17461     (write-buffered *(ebp+0x10) %eax)
17462     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
17463     (flush *(ebp+0x10))
17464     (stop *(ebp+0x14) 1)
17465     # never gets here
17466 
17467 $check-mu-index-stmt:error-index-on-stack:
17468     (write-buffered *(ebp+0x10) "fn ")
17469     8b/-> *(ebp+0xc) 0/r32/eax
17470     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17471     (write-buffered *(ebp+0x10) %eax)
17472     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
17473     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17474     (write-buffered *(ebp+0x10) %eax)
17475     (write-buffered *(ebp+0x10) "' must be in a register\n")
17476     (flush *(ebp+0x10))
17477     (stop *(ebp+0x14) 1)
17478     # never gets here
17479 
17480 $check-mu-index-stmt:error-index-needs-offset:
17481     (write-buffered *(ebp+0x10) "fn ")
17482     8b/-> *(ebp+0xc) 0/r32/eax
17483     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17484     (write-buffered *(ebp+0x10) %eax)
17485     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
17486     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17487     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17488     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17489     (write-buffered *(ebp+0x10) %eax)
17490     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
17491     (flush *(ebp+0x10))
17492     (stop *(ebp+0x14) 1)
17493     # never gets here
17494 
17495 $check-mu-index-stmt:error-too-many-inouts:
17496     (write-buffered *(ebp+0x10) "fn ")
17497     8b/-> *(ebp+0xc) 0/r32/eax
17498     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17499     (write-buffered *(ebp+0x10) %eax)
17500     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
17501     (flush *(ebp+0x10))
17502     (stop *(ebp+0x14) 1)
17503     # never gets here
17504 
17505 $check-mu-index-stmt:error-too-few-outputs:
17506     (write-buffered *(ebp+0x10) "fn ")
17507     8b/-> *(ebp+0xc) 0/r32/eax
17508     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17509     (write-buffered *(ebp+0x10) %eax)
17510     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
17511     (flush *(ebp+0x10))
17512     (stop *(ebp+0x14) 1)
17513     # never gets here
17514 
17515 $check-mu-index-stmt:error-too-many-outputs:
17516     (write-buffered *(ebp+0x10) "fn ")
17517     8b/-> *(ebp+0xc) 0/r32/eax
17518     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17519     (write-buffered *(ebp+0x10) %eax)
17520     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
17521     (flush *(ebp+0x10))
17522     (stop *(ebp+0x14) 1)
17523     # never gets here
17524 
17525 $check-mu-index-stmt:error-output-not-in-register:
17526     (write-buffered *(ebp+0x10) "fn ")
17527     8b/-> *(ebp+0xc) 0/r32/eax
17528     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17529     (write-buffered *(ebp+0x10) %eax)
17530     (write-buffered *(ebp+0x10) ": stmt index: output '")
17531     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17532     (write-buffered *(ebp+0x10) %eax)
17533     (write-buffered *(ebp+0x10) "' is not in a register\n")
17534     (flush *(ebp+0x10))
17535     (stop *(ebp+0x14) 1)
17536     # never gets here
17537 
17538 $check-mu-index-stmt:error-output-type-not-address:
17539     (write-buffered *(ebp+0x10) "fn ")
17540     8b/-> *(ebp+0xc) 0/r32/eax
17541     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17542     (write-buffered *(ebp+0x10) %eax)
17543     (write-buffered *(ebp+0x10) ": stmt index: output '")
17544     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17545     (write-buffered *(ebp+0x10) %eax)
17546     (write-buffered *(ebp+0x10) "' must be an addr\n")
17547     (flush *(ebp+0x10))
17548     (stop *(ebp+0x14) 1)
17549     # never gets here
17550 
17551 $check-mu-index-stmt:error-bad-output-type:
17552     (write-buffered *(ebp+0x10) "fn ")
17553     8b/-> *(ebp+0xc) 0/r32/eax
17554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17555     (write-buffered *(ebp+0x10) %eax)
17556     (write-buffered *(ebp+0x10) ": stmt index: output '")
17557     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17558     (write-buffered *(ebp+0x10) %eax)
17559     (write-buffered *(ebp+0x10) "' does not have the right type\n")
17560     (flush *(ebp+0x10))
17561     (stop *(ebp+0x14) 1)
17562     # never gets here
17563 
17564 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17565     # . prologue
17566     55/push-ebp
17567     89/<- %ebp 4/r32/esp
17568     # . save registers
17569     50/push-eax
17570     51/push-ecx
17571     52/push-edx
17572     53/push-ebx
17573     56/push-esi
17574     57/push-edi
17575     # esi = stmt
17576     8b/-> *(ebp+8) 6/r32/esi
17577     # - check for 0 inouts
17578     # var base/ecx: (addr var) = stmt->inouts->value
17579     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17580 $check-mu-length-stmt:check-no-inouts:
17581     3d/compare-eax-and 0/imm32
17582     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
17583     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17584     89/<- %ecx 0/r32/eax
17585     # - check base type is either (addr array ...) in register or (array ...) on stack
17586     # var base-type/ebx: (addr type-tree) = lookup(base->type)
17587     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17588     89/<- %ebx 0/r32/eax
17589     # if base-type is an atom, abort with a precise error
17590     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
17591     {
17592       74/jump-if-= break/disp8
17593       (is-simple-mu-type? %ebx 3)  # array => eax
17594       3d/compare-eax-and 0/imm32/false
17595       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
17596       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
17597     }
17598 $check-mu-length-stmt:base-is-compound:
17599     # if type->left not addr or array, abort
17600     {
17601       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17602       (is-simple-mu-type? %eax 2)  # addr => eax
17603       3d/compare-eax-and 0/imm32/false
17604       75/jump-if-!= break/disp8
17605       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17606       (is-simple-mu-type? %eax 3)  # array => eax
17607       3d/compare-eax-and 0/imm32/false
17608       75/jump-if-!= break/disp8
17609       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
17610     }
17611     # if (type->left == addr) ensure type->right->left == array and type->register exists
17612     {
17613       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17614       (is-simple-mu-type? %eax 2)  # addr => eax
17615       3d/compare-eax-and 0/imm32/false
17616       74/jump-if-= break/disp8
17617 $check-mu-length-stmt:base-is-addr:
17618       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17619       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17620       (is-simple-mu-type? %eax 3)  # array => eax
17621       3d/compare-eax-and 0/imm32/false
17622       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
17623 $check-mu-length-stmt:check-base-addr-is-register:
17624       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
17625       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
17626     }
17627     # if (type->left == array) ensure type->register doesn't exist
17628     {
17629       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17630       (is-simple-mu-type? %eax 3)  # array => eax
17631       3d/compare-eax-and 0/imm32/false
17632       74/jump-if-= break/disp8
17633 $check-mu-length-stmt:base-is-array:
17634       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
17635       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
17636     }
17637     # if (base-type->left == addr) base-type = base-type->right
17638     {
17639       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17640       (is-simple-mu-type? %eax 2)  # addr => eax
17641       3d/compare-eax-and 0/imm32/false
17642       74/jump-if-= break/disp8
17643       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17644       89/<- %ebx 0/r32/eax
17645     }
17646     # - check for too many inouts
17647     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17648     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17649     3d/compare-eax-and 0/imm32/false
17650     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
17651     # - check for 0 outputs
17652     # var output/edi: (addr var) = stmt->outputs->value
17653     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17654     3d/compare-eax-and 0/imm32/false
17655     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
17656     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17657     89/<- %edi 0/r32/eax
17658     # - check output type
17659     # must have a non-atomic type
17660     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17661     (is-simple-mu-type? %eax 1)  # int => eax
17662     3d/compare-eax-and 0/imm32/false
17663     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
17664     # - check for too many outputs
17665     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17666     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17667     3d/compare-eax-and 0/imm32/false
17668     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
17669 $check-mu-length-stmt:end:
17670     # . restore registers
17671     5f/pop-to-edi
17672     5e/pop-to-esi
17673     5b/pop-to-ebx
17674     5a/pop-to-edx
17675     59/pop-to-ecx
17676     58/pop-to-eax
17677     # . epilogue
17678     89/<- %esp 5/r32/ebp
17679     5d/pop-to-ebp
17680     c3/return
17681 
17682 $check-mu-length-stmt:error-base-non-array-type:
17683     (write-buffered *(ebp+0x10) "fn ")
17684     8b/-> *(ebp+0xc) 0/r32/eax
17685     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17686     (write-buffered *(ebp+0x10) %eax)
17687     (write-buffered *(ebp+0x10) ": stmt length: var '")
17688     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17689     (write-buffered *(ebp+0x10) %eax)
17690     (write-buffered *(ebp+0x10) "' is not an array\n")
17691     (flush *(ebp+0x10))
17692     (stop *(ebp+0x14) 1)
17693     # never gets here
17694 
17695 $check-mu-length-stmt:error-base-array-atom-type:
17696     (write-buffered *(ebp+0x10) "fn ")
17697     8b/-> *(ebp+0xc) 0/r32/eax
17698     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17699     (write-buffered *(ebp+0x10) %eax)
17700     (write-buffered *(ebp+0x10) ": stmt length: array '")
17701     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17702     (write-buffered *(ebp+0x10) %eax)
17703     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
17704     (flush *(ebp+0x10))
17705     (stop *(ebp+0x14) 1)
17706     # never gets here
17707 
17708 $check-mu-length-stmt:error-base-address-array-type-on-stack:
17709     (write-buffered *(ebp+0x10) "fn ")
17710     8b/-> *(ebp+0xc) 0/r32/eax
17711     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17712     (write-buffered *(ebp+0x10) %eax)
17713     (write-buffered *(ebp+0x10) ": stmt length: var '")
17714     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17715     (write-buffered *(ebp+0x10) %eax)
17716     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
17717     (flush *(ebp+0x10))
17718     (stop *(ebp+0x14) 1)
17719     # never gets here
17720 
17721 $check-mu-length-stmt:error-base-array-type-in-register:
17722     (write-buffered *(ebp+0x10) "fn ")
17723     8b/-> *(ebp+0xc) 0/r32/eax
17724     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17725     (write-buffered *(ebp+0x10) %eax)
17726     (write-buffered *(ebp+0x10) ": stmt length: var '")
17727     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17728     (write-buffered *(ebp+0x10) %eax)
17729     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
17730     (flush *(ebp+0x10))
17731     (stop *(ebp+0x14) 1)
17732     # never gets here
17733 
17734 $check-mu-length-stmt:error-too-few-inouts:
17735     (write-buffered *(ebp+0x10) "fn ")
17736     8b/-> *(ebp+0xc) 0/r32/eax
17737     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17738     (write-buffered *(ebp+0x10) %eax)
17739     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
17740     (flush *(ebp+0x10))
17741     (stop *(ebp+0x14) 1)
17742     # never gets here
17743 
17744 $check-mu-length-stmt:error-invalid-index-type:
17745     (write-buffered *(ebp+0x10) "fn ")
17746     8b/-> *(ebp+0xc) 0/r32/eax
17747     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17748     (write-buffered *(ebp+0x10) %eax)
17749     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
17750     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17751     (write-buffered *(ebp+0x10) %eax)
17752     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
17753     (flush *(ebp+0x10))
17754     (stop *(ebp+0x14) 1)
17755     # never gets here
17756 
17757 $check-mu-length-stmt:error-index-offset-atom-type:
17758     (write-buffered *(ebp+0x10) "fn ")
17759     8b/-> *(ebp+0xc) 0/r32/eax
17760     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17761     (write-buffered *(ebp+0x10) %eax)
17762     (write-buffered *(ebp+0x10) ": stmt length: offset '")
17763     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17764     (write-buffered *(ebp+0x10) %eax)
17765     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
17766     (flush *(ebp+0x10))
17767     (stop *(ebp+0x14) 1)
17768     # never gets here
17769 
17770 $check-mu-length-stmt:error-index-on-stack:
17771     (write-buffered *(ebp+0x10) "fn ")
17772     8b/-> *(ebp+0xc) 0/r32/eax
17773     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17774     (write-buffered *(ebp+0x10) %eax)
17775     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
17776     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17777     (write-buffered *(ebp+0x10) %eax)
17778     (write-buffered *(ebp+0x10) "' must be in a register\n")
17779     (flush *(ebp+0x10))
17780     (stop *(ebp+0x14) 1)
17781     # never gets here
17782 
17783 $check-mu-length-stmt:error-index-needs-offset:
17784     (write-buffered *(ebp+0x10) "fn ")
17785     8b/-> *(ebp+0xc) 0/r32/eax
17786     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17787     (write-buffered *(ebp+0x10) %eax)
17788     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
17789     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17790     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17791     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17792     (write-buffered *(ebp+0x10) %eax)
17793     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
17794     (flush *(ebp+0x10))
17795     (stop *(ebp+0x14) 1)
17796     # never gets here
17797 
17798 $check-mu-length-stmt:error-too-many-inouts:
17799     (write-buffered *(ebp+0x10) "fn ")
17800     8b/-> *(ebp+0xc) 0/r32/eax
17801     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17802     (write-buffered *(ebp+0x10) %eax)
17803     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
17804     (flush *(ebp+0x10))
17805     (stop *(ebp+0x14) 1)
17806     # never gets here
17807 
17808 $check-mu-length-stmt:error-too-few-outputs:
17809     (write-buffered *(ebp+0x10) "fn ")
17810     8b/-> *(ebp+0xc) 0/r32/eax
17811     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17812     (write-buffered *(ebp+0x10) %eax)
17813     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
17814     (flush *(ebp+0x10))
17815     (stop *(ebp+0x14) 1)
17816     # never gets here
17817 
17818 $check-mu-length-stmt:error-too-many-outputs:
17819     (write-buffered *(ebp+0x10) "fn ")
17820     8b/-> *(ebp+0xc) 0/r32/eax
17821     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17822     (write-buffered *(ebp+0x10) %eax)
17823     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
17824     (flush *(ebp+0x10))
17825     (stop *(ebp+0x14) 1)
17826     # never gets here
17827 
17828 $check-mu-length-stmt:error-output-not-in-register:
17829     (write-buffered *(ebp+0x10) "fn ")
17830     8b/-> *(ebp+0xc) 0/r32/eax
17831     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17832     (write-buffered *(ebp+0x10) %eax)
17833     (write-buffered *(ebp+0x10) ": stmt length: output '")
17834     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17835     (write-buffered *(ebp+0x10) %eax)
17836     (write-buffered *(ebp+0x10) "' is not in a register\n")
17837     (flush *(ebp+0x10))
17838     (stop *(ebp+0x14) 1)
17839     # never gets here
17840 
17841 $check-mu-length-stmt:error-invalid-output-type:
17842     (write-buffered *(ebp+0x10) "fn ")
17843     8b/-> *(ebp+0xc) 0/r32/eax
17844     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17845     (write-buffered *(ebp+0x10) %eax)
17846     (write-buffered *(ebp+0x10) ": stmt length: output '")
17847     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17848     (write-buffered *(ebp+0x10) %eax)
17849     (write-buffered *(ebp+0x10) "' does not have the right type\n")
17850     (flush *(ebp+0x10))
17851     (stop *(ebp+0x14) 1)
17852     # never gets here
17853 
17854 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17855     # . prologue
17856     55/push-ebp
17857     89/<- %ebp 4/r32/esp
17858     # . save registers
17859     50/push-eax
17860     51/push-ecx
17861     52/push-edx
17862     53/push-ebx
17863     56/push-esi
17864     57/push-edi
17865     # esi = stmt
17866     8b/-> *(ebp+8) 6/r32/esi
17867     # - check for 0 inouts
17868     # var base/ecx: (addr var) = stmt->inouts->value
17869     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17870 $check-mu-compute-offset-stmt:check-no-inouts:
17871     3d/compare-eax-and 0/imm32
17872     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
17873     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17874     89/<- %ecx 0/r32/eax
17875     # - check base type is either (addr array ...) in register or (array ...) on stack
17876     # var base-type/ebx: (addr type-tree) = lookup(base->type)
17877     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17878     89/<- %ebx 0/r32/eax
17879     # if base-type is an atom, abort with a precise error
17880     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
17881     {
17882       74/jump-if-= break/disp8
17883       (is-simple-mu-type? %ebx 3)  # array => eax
17884       3d/compare-eax-and 0/imm32/false
17885       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
17886       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
17887     }
17888 $check-mu-compute-offset-stmt:base-is-compound:
17889     # if type->left not addr or array, abort
17890     {
17891       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17892       (is-simple-mu-type? %eax 2)  # addr => eax
17893       3d/compare-eax-and 0/imm32/false
17894       75/jump-if-!= break/disp8
17895       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17896       (is-simple-mu-type? %eax 3)  # array => eax
17897       3d/compare-eax-and 0/imm32/false
17898       75/jump-if-!= break/disp8
17899       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
17900     }
17901     # if (type->left == addr) ensure type->right->left == array and type->register exists
17902     {
17903       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17904       (is-simple-mu-type? %eax 2)  # addr => eax
17905       3d/compare-eax-and 0/imm32/false
17906       74/jump-if-= break/disp8
17907 $check-mu-compute-offset-stmt:base-is-addr:
17908       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17909       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17910       (is-simple-mu-type? %eax 3)  # array => eax
17911       3d/compare-eax-and 0/imm32/false
17912       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
17913     }
17914     # if (base-type->left == addr) base-type = base-type->right
17915     {
17916       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17917       (is-simple-mu-type? %eax 2)  # addr => eax
17918       3d/compare-eax-and 0/imm32/false
17919       74/jump-if-= break/disp8
17920       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17921       89/<- %ebx 0/r32/eax
17922     }
17923     # - check for 1 inout
17924     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
17925     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17926     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17927 $check-mu-compute-offset-stmt:check-single-inout:
17928     3d/compare-eax-and 0/imm32
17929     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
17930     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17931     89/<- %ecx 0/r32/eax
17932     # - check index is either a literal or register
17933     # var index-type/edx: (addr type-tree)
17934     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17935     89/<- %edx 0/r32/eax
17936     # index type must be a literal or int
17937     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
17938     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
17939     {
17940 $check-mu-compute-offset-stmt:index-type-is-atom:
17941       (is-simple-mu-type? %edx 0)  # literal => eax
17942       3d/compare-eax-and 0/imm32/false
17943       75/jump-if-!= break/disp8
17944       (is-simple-mu-type? %edx 1)  # int => eax
17945       3d/compare-eax-and 0/imm32/false
17946       75/jump-if-!= break/disp8
17947       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
17948     }
17949     # - check for too many inouts
17950     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17951     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17952     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17953     3d/compare-eax-and 0/imm32/false
17954     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
17955     # - check for 0 outputs
17956     # var output/edi: (addr var) = stmt->outputs->value
17957     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17958     3d/compare-eax-and 0/imm32/false
17959     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
17960     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17961     89/<- %edi 0/r32/eax
17962     # - check output type
17963     # must have a non-atomic type
17964     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17965     89/<- %edx 0/r32/eax
17966     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
17967     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
17968     # type must start with (offset ...)
17969     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17970     (is-simple-mu-type? %eax 7)  # offset => eax
17971     3d/compare-eax-and 0/imm32/false
17972     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
17973     # if tail(base-type) != tail(output-type) abort
17974     (type-tail %ebx)  # => eax
17975     89/<- %ebx 0/r32/eax
17976     (type-tail %edx)  # => eax
17977     (type-equal? %ebx %eax)  # => eax
17978     3d/compare-eax-and 0/imm32/false
17979     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
17980     # - check for too many outputs
17981     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17982     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17983     3d/compare-eax-and 0/imm32/false
17984     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
17985 $check-mu-compute-offset-stmt:end:
17986     # . restore registers
17987     5f/pop-to-edi
17988     5e/pop-to-esi
17989     5b/pop-to-ebx
17990     5a/pop-to-edx
17991     59/pop-to-ecx
17992     58/pop-to-eax
17993     # . epilogue
17994     89/<- %esp 5/r32/ebp
17995     5d/pop-to-ebp
17996     c3/return
17997 
17998 $check-mu-compute-offset-stmt:error-base-non-array-type:
17999     (write-buffered *(ebp+0x10) "fn ")
18000     8b/-> *(ebp+0xc) 0/r32/eax
18001     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18002     (write-buffered *(ebp+0x10) %eax)
18003     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
18004     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18005     (write-buffered *(ebp+0x10) %eax)
18006     (write-buffered *(ebp+0x10) "' is not an array\n")
18007     (flush *(ebp+0x10))
18008     (stop *(ebp+0x14) 1)
18009     # never gets here
18010 
18011 $check-mu-compute-offset-stmt:error-base-array-atom-type:
18012     (write-buffered *(ebp+0x10) "fn ")
18013     8b/-> *(ebp+0xc) 0/r32/eax
18014     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18015     (write-buffered *(ebp+0x10) %eax)
18016     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
18017     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18018     (write-buffered *(ebp+0x10) %eax)
18019     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
18020     (flush *(ebp+0x10))
18021     (stop *(ebp+0x14) 1)
18022     # never gets here
18023 
18024 $check-mu-compute-offset-stmt:error-too-few-inouts:
18025     (write-buffered *(ebp+0x10) "fn ")
18026     8b/-> *(ebp+0xc) 0/r32/eax
18027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18028     (write-buffered *(ebp+0x10) %eax)
18029     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
18030     (flush *(ebp+0x10))
18031     (stop *(ebp+0x14) 1)
18032     # never gets here
18033 
18034 $check-mu-compute-offset-stmt:error-invalid-index-type:
18035     (write-buffered *(ebp+0x10) "fn ")
18036     8b/-> *(ebp+0xc) 0/r32/eax
18037     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18038     (write-buffered *(ebp+0x10) %eax)
18039     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
18040     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18041     (write-buffered *(ebp+0x10) %eax)
18042     (write-buffered *(ebp+0x10) "' must be an int\n")
18043     (flush *(ebp+0x10))
18044     (stop *(ebp+0x14) 1)
18045     # never gets here
18046 
18047 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
18048     (write-buffered *(ebp+0x10) "fn ")
18049     8b/-> *(ebp+0xc) 0/r32/eax
18050     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18051     (write-buffered *(ebp+0x10) %eax)
18052     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
18053     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18054     (write-buffered *(ebp+0x10) %eax)
18055     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
18056     (flush *(ebp+0x10))
18057     (stop *(ebp+0x14) 1)
18058     # never gets here
18059 
18060 $check-mu-compute-offset-stmt:error-index-on-stack:
18061     (write-buffered *(ebp+0x10) "fn ")
18062     8b/-> *(ebp+0xc) 0/r32/eax
18063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18064     (write-buffered *(ebp+0x10) %eax)
18065     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
18066     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18067     (write-buffered *(ebp+0x10) %eax)
18068     (write-buffered *(ebp+0x10) "' must be in a register\n")
18069     (flush *(ebp+0x10))
18070     (stop *(ebp+0x14) 1)
18071     # never gets here
18072 
18073 $check-mu-compute-offset-stmt:error-too-many-inouts:
18074     (write-buffered *(ebp+0x10) "fn ")
18075     8b/-> *(ebp+0xc) 0/r32/eax
18076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18077     (write-buffered *(ebp+0x10) %eax)
18078     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
18079     (flush *(ebp+0x10))
18080     (stop *(ebp+0x14) 1)
18081     # never gets here
18082 
18083 $check-mu-compute-offset-stmt:error-too-few-outputs:
18084     (write-buffered *(ebp+0x10) "fn ")
18085     8b/-> *(ebp+0xc) 0/r32/eax
18086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18087     (write-buffered *(ebp+0x10) %eax)
18088     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
18089     (flush *(ebp+0x10))
18090     (stop *(ebp+0x14) 1)
18091     # never gets here
18092 
18093 $check-mu-compute-offset-stmt:error-too-many-outputs:
18094     (write-buffered *(ebp+0x10) "fn ")
18095     8b/-> *(ebp+0xc) 0/r32/eax
18096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18097     (write-buffered *(ebp+0x10) %eax)
18098     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
18099     (flush *(ebp+0x10))
18100     (stop *(ebp+0x14) 1)
18101     # never gets here
18102 
18103 $check-mu-compute-offset-stmt:error-output-not-in-register:
18104     (write-buffered *(ebp+0x10) "fn ")
18105     8b/-> *(ebp+0xc) 0/r32/eax
18106     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18107     (write-buffered *(ebp+0x10) %eax)
18108     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
18109     (lookup *edi *(edi+4))  # Var-name Var-name => eax
18110     (write-buffered *(ebp+0x10) %eax)
18111     (write-buffered *(ebp+0x10) "' is not in a register\n")
18112     (flush *(ebp+0x10))
18113     (stop *(ebp+0x14) 1)
18114     # never gets here
18115 
18116 $check-mu-compute-offset-stmt:error-output-type-not-offset:
18117     (write-buffered *(ebp+0x10) "fn ")
18118     8b/-> *(ebp+0xc) 0/r32/eax
18119     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18120     (write-buffered *(ebp+0x10) %eax)
18121     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
18122     (lookup *edi *(edi+4))  # Var-name Var-name => eax
18123     (write-buffered *(ebp+0x10) %eax)
18124     (write-buffered *(ebp+0x10) "' must be an offset\n")
18125     (flush *(ebp+0x10))
18126     (stop *(ebp+0x14) 1)
18127     # never gets here
18128 
18129 $check-mu-compute-offset-stmt:error-bad-output-type:
18130     (write-buffered *(ebp+0x10) "fn ")
18131     8b/-> *(ebp+0xc) 0/r32/eax
18132     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18133     (write-buffered *(ebp+0x10) %eax)
18134     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
18135     (lookup *edi *(edi+4))  # Var-name Var-name => eax
18136     (write-buffered *(ebp+0x10) %eax)
18137     (write-buffered *(ebp+0x10) "' does not have the right type\n")
18138     (flush *(ebp+0x10))
18139     (stop *(ebp+0x14) 1)
18140     # never gets here
18141 
18142 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18143     # . prologue
18144     55/push-ebp
18145     89/<- %ebp 4/r32/esp
18146     # . save registers
18147 $check-mu-copy-object-stmt:end:
18148     # . restore registers
18149     # . epilogue
18150     89/<- %esp 5/r32/ebp
18151     5d/pop-to-ebp
18152     c3/return
18153 
18154 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18155     # . prologue
18156     55/push-ebp
18157     89/<- %ebp 4/r32/esp
18158     # . save registers
18159 $check-mu-allocate-stmt:end:
18160     # . restore registers
18161     # . epilogue
18162     89/<- %esp 5/r32/ebp
18163     5d/pop-to-ebp
18164     c3/return
18165 
18166 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18167     # . prologue
18168     55/push-ebp
18169     89/<- %ebp 4/r32/esp
18170     # . save registers
18171 $check-mu-populate-stmt:end:
18172     # . restore registers
18173     # . epilogue
18174     89/<- %esp 5/r32/ebp
18175     5d/pop-to-ebp
18176     c3/return
18177 
18178 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18179     # . prologue
18180     55/push-ebp
18181     89/<- %ebp 4/r32/esp
18182     # . save registers
18183 $check-mu-populate-stream-stmt:end:
18184     # . restore registers
18185     # . epilogue
18186     89/<- %esp 5/r32/ebp
18187     5d/pop-to-ebp
18188     c3/return
18189 
18190 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18191     # . prologue
18192     55/push-ebp
18193     89/<- %ebp 4/r32/esp
18194     # . save registers
18195     50/push-eax
18196     51/push-ecx
18197     52/push-edx
18198     53/push-ebx
18199     56/push-esi
18200     57/push-edi
18201     # esi = stmt
18202     8b/-> *(ebp+8) 6/r32/esi
18203     # - check for 0 inouts
18204     # var base/ecx: (addr var) = stmt->inouts->value
18205     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18206 $check-mu-read-from-stream-stmt:check-no-inouts:
18207     3d/compare-eax-and 0/imm32
18208     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
18209     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18210     89/<- %ecx 0/r32/eax
18211     # - check base type is (addr stream T)
18212     # var base-type/ebx: (addr type-tree) = lookup(base->type)
18213     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18214     89/<- %ebx 0/r32/eax
18215 $check-mu-read-from-stream-stmt:check-base-is-compound:
18216     # if base-type is an atom, abort
18217     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
18218     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
18219 $check-mu-read-from-stream-stmt:check-base-is-addr:
18220     # if type->left not addr, abort
18221     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
18222     (is-simple-mu-type? %eax 2)  # addr => eax
18223     3d/compare-eax-and 0/imm32/false
18224     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
18225 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
18226     # base-type = base-type->right
18227     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
18228     89/<- %ebx 0/r32/eax
18229     # ensure base-type->left == stream
18230     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18231     (is-simple-mu-type? %eax 0xb)  # stream => eax
18232     3d/compare-eax-and 0/imm32/false
18233     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
18234     # - check target type is (addr T)
18235     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
18236     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18237     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18238 $check-mu-read-from-stream-stmt:check-single-inout:
18239     3d/compare-eax-and 0/imm32
18240     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
18241     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18242     89/<- %ecx 0/r32/eax
18243     # var target-type/edx: (addr type-tree)
18244     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18245     89/<- %edx 0/r32/eax
18246     # if target-type is an atom, it must be a literal or int
18247 $check-mu-read-from-stream-stmt:check-target-is-compound:
18248     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
18249     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
18250 $check-mu-read-from-stream-stmt:check-target-type:
18251     # target type must start with (addr ...)
18252     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
18253     (is-simple-mu-type? %eax 2)  # addr => eax
18254     3d/compare-eax-and 0/imm32/false
18255     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
18256     # if tail(base-type) != tail(target-type) abort
18257     (type-tail %ebx)  # => eax
18258     89/<- %ebx 0/r32/eax
18259     (type-tail %edx)  # => eax
18260     (type-equal? %ebx %eax)  # => eax
18261     3d/compare-eax-and 0/imm32/false
18262     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
18263 $check-mu-read-from-stream-stmt:check-too-many-inouts:
18264     # - check for too many inouts
18265     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18266     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18267     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18268     3d/compare-eax-and 0/imm32/false
18269     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
18270 $check-mu-read-from-stream-stmt:check-unexpected-output:
18271     # - check for any output
18272     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
18273     3d/compare-eax-and 0/imm32/false
18274     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
18275 $check-mu-read-from-stream-stmt:end:
18276     # . restore registers
18277     5f/pop-to-edi
18278     5e/pop-to-esi
18279     5b/pop-to-ebx
18280     5a/pop-to-edx
18281     59/pop-to-ecx
18282     58/pop-to-eax
18283     # . epilogue
18284     89/<- %esp 5/r32/ebp
18285     5d/pop-to-ebp
18286     c3/return
18287 
18288 $check-mu-read-from-stream-stmt:error-invalid-base-type:
18289     (write-buffered *(ebp+0x10) "fn ")
18290     8b/-> *(ebp+0xc) 0/r32/eax
18291     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18292     (write-buffered *(ebp+0x10) %eax)
18293     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
18294     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18295     (write-buffered *(ebp+0x10) %eax)
18296     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
18297     (flush *(ebp+0x10))
18298     (stop *(ebp+0x14) 1)
18299     # never gets here
18300 
18301 $check-mu-read-from-stream-stmt:error-too-few-inouts:
18302     (write-buffered *(ebp+0x10) "fn ")
18303     8b/-> *(ebp+0xc) 0/r32/eax
18304     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18305     (write-buffered *(ebp+0x10) %eax)
18306     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
18307     (flush *(ebp+0x10))
18308     (stop *(ebp+0x14) 1)
18309     # never gets here
18310 
18311 $check-mu-read-from-stream-stmt:error-target-type-not-address:
18312     (write-buffered *(ebp+0x10) "fn ")
18313     8b/-> *(ebp+0xc) 0/r32/eax
18314     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18315     (write-buffered *(ebp+0x10) %eax)
18316     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
18317     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18318     (write-buffered *(ebp+0x10) %eax)
18319     (write-buffered *(ebp+0x10) "' must be an addr\n")
18320     (flush *(ebp+0x10))
18321     (stop *(ebp+0x14) 1)
18322     # never gets here
18323 
18324 $check-mu-read-from-stream-stmt:error-invalid-target-type:
18325     (write-buffered *(ebp+0x10) "fn ")
18326     8b/-> *(ebp+0xc) 0/r32/eax
18327     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18328     (write-buffered *(ebp+0x10) %eax)
18329     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
18330     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18331     (write-buffered *(ebp+0x10) %eax)
18332     (write-buffered *(ebp+0x10) "' does not have the right type\n")
18333     (flush *(ebp+0x10))
18334     (stop *(ebp+0x14) 1)
18335     # never gets here
18336 
18337 $check-mu-read-from-stream-stmt:error-too-many-inouts:
18338     (write-buffered *(ebp+0x10) "fn ")
18339     8b/-> *(ebp+0xc) 0/r32/eax
18340     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18341     (write-buffered *(ebp+0x10) %eax)
18342     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
18343     (flush *(ebp+0x10))
18344     (stop *(ebp+0x14) 1)
18345     # never gets here
18346 
18347 $check-mu-read-from-stream-stmt:error-unexpected-output:
18348     (write-buffered *(ebp+0x10) "fn ")
18349     8b/-> *(ebp+0xc) 0/r32/eax
18350     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18351     (write-buffered *(ebp+0x10) %eax)
18352     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
18353     (flush *(ebp+0x10))
18354     (stop *(ebp+0x14) 1)
18355     # never gets here
18356 
18357 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18358     # . prologue
18359     55/push-ebp
18360     89/<- %ebp 4/r32/esp
18361     # . save registers
18362     50/push-eax
18363     51/push-ecx
18364     52/push-edx
18365     53/push-ebx
18366     56/push-esi
18367     57/push-edi
18368     # esi = stmt
18369     8b/-> *(ebp+8) 6/r32/esi
18370     # - check for 0 inouts
18371     # var base/ecx: (addr var) = stmt->inouts->value
18372     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18373 $check-mu-write-to-stream-stmt:check-no-inouts:
18374     3d/compare-eax-and 0/imm32
18375     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
18376     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18377     89/<- %ecx 0/r32/eax
18378     # - check base type is (addr stream T)
18379     # var base-type/ebx: (addr type-tree) = lookup(base->type)
18380     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18381     89/<- %ebx 0/r32/eax
18382 $check-mu-write-to-stream-stmt:check-base-is-compound:
18383     # if base-type is an atom, abort
18384     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
18385     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
18386 $check-mu-write-to-stream-stmt:check-base-is-addr:
18387     # if type->left not addr, abort
18388     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
18389     (is-simple-mu-type? %eax 2)  # addr => eax
18390     3d/compare-eax-and 0/imm32/false
18391     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
18392 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
18393     # base-type = base-type->right
18394     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
18395     89/<- %ebx 0/r32/eax
18396     # ensure base-type->left == stream
18397     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18398     (is-simple-mu-type? %eax 0xb)  # stream => eax
18399     3d/compare-eax-and 0/imm32/false
18400     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
18401     # - check target type is (addr T)
18402     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
18403     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18404     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18405 $check-mu-write-to-stream-stmt:check-single-inout:
18406     3d/compare-eax-and 0/imm32
18407     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
18408     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18409     89/<- %ecx 0/r32/eax
18410     # var target-type/edx: (addr type-tree)
18411     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18412     89/<- %edx 0/r32/eax
18413     # if target-type is an atom, it must be a literal or int
18414 $check-mu-write-to-stream-stmt:check-target-is-compound:
18415     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
18416     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
18417 $check-mu-write-to-stream-stmt:check-target-type:
18418     # target type must start with (addr ...)
18419     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
18420     (is-simple-mu-type? %eax 2)  # addr => eax
18421     3d/compare-eax-and 0/imm32/false
18422     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
18423     # if tail(base-type) != tail(target-type) abort
18424     (type-tail %ebx)  # => eax
18425     89/<- %ebx 0/r32/eax
18426     (type-tail %edx)  # => eax
18427     (type-equal? %ebx %eax)  # => eax
18428     3d/compare-eax-and 0/imm32/false
18429     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
18430 $check-mu-write-to-stream-stmt:check-too-many-inouts:
18431     # - check for too many inouts
18432     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18433     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18434     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18435     3d/compare-eax-and 0/imm32/false
18436     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
18437 $check-mu-write-to-stream-stmt:check-unexpected-output:
18438     # - check for any output
18439     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
18440     3d/compare-eax-and 0/imm32/false
18441     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
18442 $check-mu-write-to-stream-stmt:end:
18443     # . restore registers
18444     5f/pop-to-edi
18445     5e/pop-to-esi
18446     5b/pop-to-ebx
18447     5a/pop-to-edx
18448     59/pop-to-ecx
18449     58/pop-to-eax
18450     # . epilogue
18451     89/<- %esp 5/r32/ebp
18452     5d/pop-to-ebp
18453     c3/return
18454 
18455 $check-mu-write-to-stream-stmt:error-invalid-base-type:
18456     (write-buffered *(ebp+0x10) "fn ")
18457     8b/-> *(ebp+0xc) 0/r32/eax
18458     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18459     (write-buffered *(ebp+0x10) %eax)
18460     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
18461     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18462     (write-buffered *(ebp+0x10) %eax)
18463     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
18464     (flush *(ebp+0x10))
18465     (stop *(ebp+0x14) 1)
18466     # never gets here
18467 
18468 $check-mu-write-to-stream-stmt:error-too-few-inouts:
18469     (write-buffered *(ebp+0x10) "fn ")
18470     8b/-> *(ebp+0xc) 0/r32/eax
18471     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18472     (write-buffered *(ebp+0x10) %eax)
18473     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
18474     (flush *(ebp+0x10))
18475     (stop *(ebp+0x14) 1)
18476     # never gets here
18477 
18478 $check-mu-write-to-stream-stmt:error-target-type-not-address:
18479     (write-buffered *(ebp+0x10) "fn ")
18480     8b/-> *(ebp+0xc) 0/r32/eax
18481     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18482     (write-buffered *(ebp+0x10) %eax)
18483     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
18484     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18485     (write-buffered *(ebp+0x10) %eax)
18486     (write-buffered *(ebp+0x10) "' must be an addr\n")
18487     (flush *(ebp+0x10))
18488     (stop *(ebp+0x14) 1)
18489     # never gets here
18490 
18491 $check-mu-write-to-stream-stmt:error-invalid-target-type:
18492     (write-buffered *(ebp+0x10) "fn ")
18493     8b/-> *(ebp+0xc) 0/r32/eax
18494     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18495     (write-buffered *(ebp+0x10) %eax)
18496     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
18497     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18498     (write-buffered *(ebp+0x10) %eax)
18499     (write-buffered *(ebp+0x10) "' does not have the right type\n")
18500     (flush *(ebp+0x10))
18501     (stop *(ebp+0x14) 1)
18502     # never gets here
18503 
18504 $check-mu-write-to-stream-stmt:error-too-many-inouts:
18505     (write-buffered *(ebp+0x10) "fn ")
18506     8b/-> *(ebp+0xc) 0/r32/eax
18507     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18508     (write-buffered *(ebp+0x10) %eax)
18509     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
18510     (flush *(ebp+0x10))
18511     (stop *(ebp+0x14) 1)
18512     # never gets here
18513 
18514 $check-mu-write-to-stream-stmt:error-unexpected-output:
18515     (write-buffered *(ebp+0x10) "fn ")
18516     8b/-> *(ebp+0xc) 0/r32/eax
18517     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18518     (write-buffered *(ebp+0x10) %eax)
18519     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
18520     (flush *(ebp+0x10))
18521     (stop *(ebp+0x14) 1)
18522     # never gets here
18523 
18524 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18525     # . prologue
18526     55/push-ebp
18527     89/<- %ebp 4/r32/esp
18528     # . save registers
18529 $check-mu-convert-stmt:end:
18530     # . restore registers
18531     # . epilogue
18532     89/<- %esp 5/r32/ebp
18533     5d/pop-to-ebp
18534     c3/return
18535 
18536 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18537     # . prologue
18538     55/push-ebp
18539     89/<- %ebp 4/r32/esp
18540     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
18541     68/push 0/imm32
18542     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
18543     81 5/subop/subtract %esp 0x60/imm32
18544     68/push 0x60/imm32/size
18545     68/push 0/imm32/read
18546     68/push 0/imm32/write
18547     # save a pointer to type-parameters-storage at type-parameters
18548     89/<- *(ebp-4) 4/r32/esp
18549     (clear-stream *(ebp-4))
18550     # . save registers
18551     50/push-eax
18552     51/push-ecx
18553     52/push-edx
18554     53/push-ebx
18555     56/push-esi
18556     57/push-edi
18557     # esi = stmt
18558     8b/-> *(ebp+8) 6/r32/esi
18559     # edi = callee
18560     8b/-> *(ebp+0xc) 7/r32/edi
18561     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
18562     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18563     89/<- %ecx 0/r32/eax
18564     # var expected/edx: (addr list var) = lookup(f->inouts)
18565     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
18566     89/<- %edx 0/r32/eax
18567     {
18568 $check-mu-call:check-for-inouts:
18569       # if (inouts == 0) break
18570       81 7/subop/compare %ecx 0/imm32
18571       0f 84/jump-if-= break/disp32
18572       # if (expected == 0) error
18573       81 7/subop/compare %edx 0/imm32
18574       0f 84/jump-if-= break/disp32
18575 $check-mu-call:check-inout-type:
18576       # var v/eax: (addr v) = lookup(inouts->value)
18577       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18578       # var t/ebx: (addr type-tree) = lookup(v->type)
18579       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18580       89/<- %ebx 0/r32/eax
18581       # if (inouts->is-deref?) t = t->right  # TODO: check that t->left is an addr
18582       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
18583       {
18584         74/jump-if-= break/disp8
18585         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
18586         89/<- %ebx 0/r32/eax
18587         # if t->right is null, t = t->left
18588         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
18589         75/jump-if-!= break/disp8
18590         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
18591         89/<- %ebx 0/r32/eax
18592       }
18593       # var v2/eax: (addr v) = lookup(expected->value)
18594       (lookup *edx *(edx+4))  # List-value List-value => eax
18595       # var t2/eax: (addr type-tree) = lookup(v2->type)
18596       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18597       # if (t != t2) error
18598       (type-match? %eax %ebx *(ebp-4))  # => eax
18599       3d/compare-eax-and 0/imm32/false
18600       {
18601         0f 85/jump-if-!= break/disp32
18602         (write-buffered *(ebp+0x14) "fn ")
18603         8b/-> *(ebp+0x10) 0/r32/eax
18604         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18605         (write-buffered *(ebp+0x14) %eax)
18606         (write-buffered *(ebp+0x14) ": call ")
18607         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18608         (write-buffered *(ebp+0x14) %eax)
18609         (write-buffered *(ebp+0x14) ": type for inout '")
18610         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18611         (lookup *eax *(eax+4))  # Var-name Var-name => eax
18612         (write-buffered *(ebp+0x14) %eax)
18613         (write-buffered *(ebp+0x14) "' is not right\n")
18614         (flush *(ebp+0x14))
18615         (stop *(ebp+0x18) 1)
18616       }
18617 $check-mu-call:continue-to-next-inout:
18618       # inouts = lookup(inouts->next)
18619       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
18620       89/<- %ecx 0/r32/eax
18621       # expected = lookup(expected->next)
18622       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
18623       89/<- %edx 0/r32/eax
18624       #
18625       e9/jump loop/disp32
18626     }
18627 $check-mu-call:check-inout-count:
18628     # if (inouts == expected) proceed
18629     39/compare %ecx 2/r32/edx
18630     {
18631       0f 84/jump-if-= break/disp32
18632       # exactly one of the two is null
18633       # if (inouts == 0) error("too many inouts")
18634       {
18635         81 7/subop/compare %ecx 0/imm32
18636         0f 84/jump-if-= break/disp32
18637         (write-buffered *(ebp+0x14) "fn ")
18638         8b/-> *(ebp+0x10) 0/r32/eax
18639         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18640         (write-buffered *(ebp+0x14) %eax)
18641         (write-buffered *(ebp+0x14) ": call ")
18642         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18643         (write-buffered *(ebp+0x14) %eax)
18644         (write-buffered *(ebp+0x14) ": too many inouts\n")
18645         (flush *(ebp+0x14))
18646         (stop *(ebp+0x18) 1)
18647       }
18648       # if (expected == 0) error("too few inouts")
18649       {
18650         81 7/subop/compare %edx 0/imm32
18651         0f 84/jump-if-= break/disp32
18652         (write-buffered *(ebp+0x14) "fn ")
18653         8b/-> *(ebp+0x10) 0/r32/eax
18654         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18655         (write-buffered *(ebp+0x14) %eax)
18656         (write-buffered *(ebp+0x14) ": call ")
18657         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18658         (write-buffered *(ebp+0x14) %eax)
18659         (write-buffered *(ebp+0x14) ": too few inouts\n")
18660         (flush *(ebp+0x14))
18661         (stop *(ebp+0x18) 1)
18662       }
18663     }
18664 $check-mu-call:check-outputs:
18665     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
18666     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
18667     89/<- %ecx 0/r32/eax
18668     # var expected/edx: (addr list var) = lookup(f->outputs)
18669     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
18670     89/<- %edx 0/r32/eax
18671     {
18672 $check-mu-call:check-for-outputs:
18673       # if (outputs == 0) break
18674       81 7/subop/compare %ecx 0/imm32
18675       0f 84/jump-if-= break/disp32
18676       # if (expected == 0) error
18677       81 7/subop/compare %edx 0/imm32
18678       0f 84/jump-if-= break/disp32
18679 $check-mu-call:check-output-type:
18680       # var v/eax: (addr v) = lookup(outputs->value)
18681       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18682       # var t/ebx: (addr type-tree) = lookup(v->type)
18683       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18684       89/<- %ebx 0/r32/eax
18685       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
18686       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
18687       {
18688         74/jump-if-= break/disp8
18689         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
18690         89/<- %ebx 0/r32/eax
18691       }
18692       # var v2/eax: (addr v) = lookup(expected->value)
18693       (lookup *edx *(edx+4))  # List-value List-value => eax
18694       # var t2/eax: (addr type-tree) = lookup(v2->type)
18695       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18696       # if (t != t2) error
18697       (type-match? %eax %ebx *(ebp-4))  # => eax
18698       3d/compare-eax-and 0/imm32/false
18699       {
18700         0f 85/jump-if-!= break/disp32
18701         (write-buffered *(ebp+0x14) "fn ")
18702         8b/-> *(ebp+0x10) 0/r32/eax
18703         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18704         (write-buffered *(ebp+0x14) %eax)
18705         (write-buffered *(ebp+0x14) ": call ")
18706         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18707         (write-buffered *(ebp+0x14) %eax)
18708         (write-buffered *(ebp+0x14) ": type for output '")
18709         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18710         (lookup *eax *(eax+4))  # Var-name Var-name => eax
18711         (write-buffered *(ebp+0x14) %eax)
18712         (write-buffered *(ebp+0x14) "' is not right\n")
18713         (flush *(ebp+0x14))
18714         (stop *(ebp+0x18) 1)
18715       }
18716 $check-mu-call:check-output-register:
18717       # var v/eax: (addr v) = lookup(outputs->value)
18718       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18719       # var r/ebx: (addr array byte) = lookup(v->register)
18720       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
18721       89/<- %ebx 0/r32/eax
18722       # if (r == 0) error
18723       3d/compare-eax-and 0/imm32
18724       {
18725         0f 85/jump-if-!= break/disp32
18726         (write-buffered *(ebp+0x14) "fn ")
18727         8b/-> *(ebp+0x10) 0/r32/eax
18728         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18729         (write-buffered *(ebp+0x14) %eax)
18730         (write-buffered *(ebp+0x14) ": call ")
18731         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18732         (write-buffered *(ebp+0x14) %eax)
18733         (write-buffered *(ebp+0x14) ": output '")
18734         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18735         (lookup *eax *(eax+4))  # Var-name Var-name => eax
18736         (write-buffered *(ebp+0x14) %eax)
18737         (write-buffered *(ebp+0x14) "' is not in a register\n")
18738         (flush *(ebp+0x14))
18739         (stop *(ebp+0x18) 1)
18740       }
18741       # var v2/eax: (addr v) = lookup(expected->value)
18742       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
18743       # var r2/eax: (addr array byte) = lookup(v2->register)
18744       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
18745       # if (r != r2) error
18746       (string-equal? %eax %ebx)  # => eax
18747       3d/compare-eax-and 0/imm32/false
18748       {
18749         0f 85/jump-if-!= break/disp32
18750         (write-buffered *(ebp+0x14) "fn ")
18751         8b/-> *(ebp+0x10) 0/r32/eax
18752         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18753         (write-buffered *(ebp+0x14) %eax)
18754         (write-buffered *(ebp+0x14) ": call ")
18755         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18756         (write-buffered *(ebp+0x14) %eax)
18757         (write-buffered *(ebp+0x14) ": register for output '")
18758         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
18759         (lookup *eax *(eax+4))  # Var-name Var-name => eax
18760         (write-buffered *(ebp+0x14) %eax)
18761         (write-buffered *(ebp+0x14) "' is not right\n")
18762         (flush *(ebp+0x14))
18763         (stop *(ebp+0x18) 1)
18764       }
18765 $check-mu-call:continue-to-next-output:
18766       # outputs = lookup(outputs->next)
18767       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
18768       89/<- %ecx 0/r32/eax
18769       # expected = lookup(expected->next)
18770       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
18771       89/<- %edx 0/r32/eax
18772       #
18773       e9/jump loop/disp32
18774     }
18775 $check-mu-call:check-output-count:
18776     # if (outputs == expected) proceed
18777     39/compare %ecx 2/r32/edx
18778     {
18779       0f 84/jump-if-= break/disp32
18780       # exactly one of the two is null
18781       # if (outputs == 0) error("too many outputs")
18782       {
18783         81 7/subop/compare %ecx 0/imm32
18784         0f 84/jump-if-= break/disp32
18785         (write-buffered *(ebp+0x14) "fn ")
18786         8b/-> *(ebp+0x10) 0/r32/eax
18787         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18788         (write-buffered *(ebp+0x14) %eax)
18789         (write-buffered *(ebp+0x14) ": call ")
18790         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18791         (write-buffered *(ebp+0x14) %eax)
18792         (write-buffered *(ebp+0x14) ": too many outputs\n")
18793         (flush *(ebp+0x14))
18794         (stop *(ebp+0x18) 1)
18795       }
18796       # if (expected == 0) error("too few outputs")
18797       {
18798         81 7/subop/compare %edx 0/imm32
18799         0f 84/jump-if-= break/disp32
18800         (write-buffered *(ebp+0x14) "fn ")
18801         8b/-> *(ebp+0x10) 0/r32/eax
18802         (lookup *eax *(eax+4))  # Function-name Function-name => eax
18803         (write-buffered *(ebp+0x14) %eax)
18804         (write-buffered *(ebp+0x14) ": call ")
18805         (lookup *edi *(edi+4))  # Function-name Function-name => eax
18806         (write-buffered *(ebp+0x14) %eax)
18807         (write-buffered *(ebp+0x14) ": too few outputs\n")
18808         (flush *(ebp+0x14))
18809         (stop *(ebp+0x18) 1)
18810       }
18811     }
18812 $check-mu-call:end:
18813     # . restore registers
18814     5f/pop-to-edi
18815     5e/pop-to-esi
18816     5b/pop-to-ebx
18817     5a/pop-to-edx
18818     59/pop-to-ecx
18819     58/pop-to-eax
18820     # . reclaim locals exclusively on the stack
18821     81 0/subop/add %esp 0x70/imm32
18822     # . epilogue
18823     89/<- %esp 5/r32/ebp
18824     5d/pop-to-ebp
18825     c3/return
18826 
18827 # like type-equal? but takes literals into account
18828 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
18829     # . prologue
18830     55/push-ebp
18831     89/<- %ebp 4/r32/esp
18832     # if (call == literal) return true  # TODO: more precise
18833     (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
18834     3d/compare-eax-and 0/imm32/false
18835     b8/copy-to-eax 1/imm32/true
18836     75/jump-if-!= $type-match?:end/disp8
18837 $type-match?:baseline:
18838     # otherwise fall back
18839     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
18840 $type-match?:end:
18841     # . epilogue
18842     89/<- %esp 5/r32/ebp
18843     5d/pop-to-ebp
18844     c3/return
18845 
18846 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
18847     # . prologue
18848     55/push-ebp
18849     89/<- %ebp 4/r32/esp
18850     # . save registers
18851     51/push-ecx
18852     52/push-edx
18853     53/push-ebx
18854     # ecx = def
18855     8b/-> *(ebp+8) 1/r32/ecx
18856     # edx = call
18857     8b/-> *(ebp+0xc) 2/r32/edx
18858 $type-component-match?:compare-addr:
18859     # if (def == call) return true
18860     8b/-> %ecx 0/r32/eax  # Var-type
18861     39/compare %edx 0/r32/eax  # Var-type
18862     b8/copy-to-eax 1/imm32/true
18863     0f 84/jump-if-= $type-component-match?:end/disp32
18864     # if (def == 0) return false
18865     b8/copy-to-eax 0/imm32/false
18866     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
18867     0f 84/jump-if-= $type-component-match?:end/disp32
18868     # if (call == 0) return false
18869     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
18870     0f 84/jump-if-= $type-component-match?:end/disp32
18871     # if def is a type parameter, just check in type-parameters
18872     {
18873 $type-component-match?:check-type-parameter:
18874       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18875       74/jump-if-= break/disp8
18876       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
18877       75/jump-if-!= break/disp8
18878 $type-component-match?:type-parameter:
18879       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
18880       e9/jump $type-component-match?:end/disp32
18881     }
18882     # if def is a list containing just a type parameter, just check in type-parameters
18883     {
18884 $type-component-match?:check-list-type-parameter:
18885       # if def is a list..
18886       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18887       75/jump-if-!= break/disp8
18888       #   ..that's a singleton
18889       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
18890       75/jump-if-!= break/disp8
18891       #   ..and whose head is a type parameter
18892       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18893       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
18894       74/jump-if-= break/disp8
18895       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
18896       75/jump-if-!= break/disp8
18897 $type-component-match?:list-type-parameter:
18898       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
18899       e9/jump $type-component-match?:end/disp32
18900     }
18901 $type-component-match?:compare-atom-state:
18902     # if (def->is-atom? != call->is-atom?) return false
18903     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
18904     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
18905     b8/copy-to-eax 0/imm32/false
18906     0f 85/jump-if-!= $type-component-match?:end/disp32
18907     # if def->is-atom? return (def->value == call->value)
18908     {
18909 $type-component-match?:check-atom:
18910       81 7/subop/compare %ebx 0/imm32/false
18911       74/jump-if-= break/disp8
18912 $type-component-match?:is-atom:
18913       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
18914       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
18915       0f 94/set-if-= %al
18916       81 4/subop/and %eax 0xff/imm32
18917       e9/jump $type-component-match?:end/disp32
18918     }
18919 $type-component-match?:check-left:
18920     # if (!type-component-match?(def->left, call->left)) return false
18921     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18922     89/<- %ebx 0/r32/eax
18923     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
18924     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
18925     3d/compare-eax-and 0/imm32/false
18926     74/jump-if-= $type-component-match?:end/disp8
18927 $type-component-match?:check-right:
18928     # return type-component-match?(def->right, call->right)
18929     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18930     89/<- %ebx 0/r32/eax
18931     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
18932     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
18933 $type-component-match?:end:
18934     # . restore registers
18935     5b/pop-to-ebx
18936     5a/pop-to-edx
18937     59/pop-to-ecx
18938     # . epilogue
18939     89/<- %esp 5/r32/ebp
18940     5d/pop-to-ebp
18941     c3/return
18942 
18943 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
18944     # . prologue
18945     55/push-ebp
18946     89/<- %ebp 4/r32/esp
18947     # . save registers
18948     51/push-ecx
18949     #
18950     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
18951     # if parameter wasn't saved, save it
18952     {
18953       81 7/subop/compare *eax 0/imm32
18954       75/jump-if-!= break/disp8
18955       8b/-> *(ebp+0x10) 1/r32/ecx
18956       89/<- *eax 1/r32/ecx
18957     }
18958     #
18959     (type-equal? *(ebp+0x10) *eax)  # => eax
18960 $type-parameter-match?:end:
18961     # . restore registers
18962     59/pop-to-ecx
18963     # . epilogue
18964     89/<- %esp 5/r32/ebp
18965     5d/pop-to-ebp
18966     c3/return
18967 
18968 size-of:  # v: (addr var) -> result/eax: int
18969     # . prologue
18970     55/push-ebp
18971     89/<- %ebp 4/r32/esp
18972     # . save registers
18973     51/push-ecx
18974     # var t/ecx: (addr type-tree) = lookup(v->type)
18975     8b/-> *(ebp+8) 1/r32/ecx
18976 #?     (write-buffered Stderr "size-of ")
18977 #?     (write-int32-hex-buffered Stderr %ecx)
18978 #?     (write-buffered Stderr Newline)
18979 #?     (write-buffered Stderr "type allocid: ")
18980 #?     (write-int32-hex-buffered Stderr *(ecx+8))
18981 #?     (write-buffered Stderr Newline)
18982 #?     (flush Stderr)
18983     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18984     89/<- %ecx 0/r32/eax
18985     # if is-mu-array?(t) return size-of-array(t)
18986     {
18987       (is-mu-array? %ecx)  # => eax
18988       3d/compare-eax-and 0/imm32/false
18989       74/jump-if-= break/disp8
18990       (size-of-array %ecx)  # => eax
18991       eb/jump $size-of:end/disp8
18992     }
18993     # if is-mu-stream?(t) return size-of-stream(t)
18994     {
18995       (is-mu-stream? %ecx)  # => eax
18996       3d/compare-eax-and 0/imm32/false
18997       74/jump-if-= break/disp8
18998       (size-of-stream %ecx)  # => eax
18999       eb/jump $size-of:end/disp8
19000     }
19001     # if (!t->is-atom?) t = lookup(t->left)
19002     {
19003       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19004       75/jump-if-!= break/disp8
19005       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19006       89/<- %ecx 0/r32/eax
19007     }
19008     # TODO: assert t->is-atom?
19009     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
19010 $size-of:end:
19011     # . restore registers
19012     59/pop-to-ecx
19013     # . epilogue
19014     89/<- %esp 5/r32/ebp
19015     5d/pop-to-ebp
19016     c3/return
19017 
19018 size-of-deref:  # v: (addr var) -> result/eax: int
19019     # . prologue
19020     55/push-ebp
19021     89/<- %ebp 4/r32/esp
19022     # . save registers
19023     51/push-ecx
19024     # var t/ecx: (addr type-tree) = lookup(v->type)
19025     8b/-> *(ebp+8) 1/r32/ecx
19026     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19027     89/<- %ecx 0/r32/eax
19028     # TODO: assert(t is an addr)
19029     # t = lookup(t->right)
19030     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19031     89/<- %ecx 0/r32/eax
19032     # if is-mu-array?(t) return size-of-array(t)
19033     {
19034       (is-mu-array? %ecx)  # => eax
19035       3d/compare-eax-and 0/imm32/false
19036       74/jump-if-= break/disp8
19037       (size-of-array %ecx)  # => eax
19038       eb/jump $size-of-deref:end/disp8
19039     }
19040     # if is-mu-stream?(t) return size-of-stream(t)
19041     {
19042       (is-mu-stream? %ecx)  # => eax
19043       3d/compare-eax-and 0/imm32/false
19044       74/jump-if-= break/disp8
19045       (size-of-stream %ecx)  # => eax
19046       eb/jump $size-of-deref:end/disp8
19047     }
19048     # if (!t->is-atom?) t = lookup(t->left)
19049     {
19050       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19051       75/jump-if-!= break/disp8
19052       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19053       89/<- %ecx 0/r32/eax
19054     }
19055     # TODO: assert t->is-atom?
19056     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
19057 $size-of-deref:end:
19058     # . restore registers
19059     59/pop-to-ecx
19060     # . epilogue
19061     89/<- %esp 5/r32/ebp
19062     5d/pop-to-ebp
19063     c3/return
19064 
19065 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
19066     # . prologue
19067     55/push-ebp
19068     89/<- %ebp 4/r32/esp
19069     # . save registers
19070     51/push-ecx
19071     # ecx = t
19072     8b/-> *(ebp+8) 1/r32/ecx
19073     # if t->is-atom?, return false
19074     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19075     75/jump-if-!= $is-mu-array?:return-false/disp8
19076     # if !t->left->is-atom?, return false
19077     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19078     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
19079     74/jump-if-= $is-mu-array?:return-false/disp8
19080     # return t->left->value == array
19081     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
19082     0f 94/set-if-= %al
19083     81 4/subop/and %eax 0xff/imm32
19084     eb/jump $is-mu-array?:end/disp8
19085 $is-mu-array?:return-false:
19086     b8/copy-to-eax 0/imm32/false
19087 $is-mu-array?:end:
19088     # . restore registers
19089     59/pop-to-ecx
19090     # . epilogue
19091     89/<- %esp 5/r32/ebp
19092     5d/pop-to-ebp
19093     c3/return
19094 
19095 # size of a statically allocated array where the size is part of the type expression
19096 size-of-array:  # a: (addr type-tree) -> result/eax: int
19097     # . prologue
19098     55/push-ebp
19099     89/<- %ebp 4/r32/esp
19100     # . save registers
19101     51/push-ecx
19102     52/push-edx
19103     #
19104     8b/-> *(ebp+8) 1/r32/ecx
19105     # TODO: assert that a->left is 'array'
19106     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19107     89/<- %ecx 0/r32/eax
19108     # var elem-type/edx: type-id = a->right->left->value
19109     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19110     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
19111     # TODO: assert that a->right->right->left->value == size
19112     # var array-size/ecx: int = a->right->right->left->value-size
19113     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19114     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19115     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
19116     # return 4 + array-size * size-of(elem-type)
19117     (size-of-type-id-as-array-element %edx)  # => eax
19118     f7 4/subop/multiply-into-edx-eax %ecx
19119     05/add-to-eax 4/imm32  # for array size
19120     # TODO: check edx for overflow
19121 $size-of-array:end:
19122     # . restore registers
19123     5a/pop-to-edx
19124     59/pop-to-ecx
19125     # . epilogue
19126     89/<- %esp 5/r32/ebp
19127     5d/pop-to-ebp
19128     c3/return
19129 
19130 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
19131     # . prologue
19132     55/push-ebp
19133     89/<- %ebp 4/r32/esp
19134     # . save registers
19135     51/push-ecx
19136     # ecx = t
19137     8b/-> *(ebp+8) 1/r32/ecx
19138     # if t->is-atom?, return false
19139     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19140     75/jump-if-!= $is-mu-stream?:return-false/disp8
19141     # if !t->left->is-atom?, return false
19142     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19143     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
19144     74/jump-if-= $is-mu-stream?:return-false/disp8
19145     # return t->left->value == stream
19146     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
19147     0f 94/set-if-= %al
19148     81 4/subop/and %eax 0xff/imm32
19149     eb/jump $is-mu-stream?:end/disp8
19150 $is-mu-stream?:return-false:
19151     b8/copy-to-eax 0/imm32/false
19152 $is-mu-stream?:end:
19153     # . restore registers
19154     59/pop-to-ecx
19155     # . epilogue
19156     89/<- %esp 5/r32/ebp
19157     5d/pop-to-ebp
19158     c3/return
19159 
19160 # size of a statically allocated stream where the size is part of the type expression
19161 size-of-stream:  # a: (addr type-tree) -> result/eax: int
19162     # . prologue
19163     55/push-ebp
19164     89/<- %ebp 4/r32/esp
19165     #
19166     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
19167     05/add-to-eax 8/imm32  # for read/write pointers
19168 $size-of-stream:end:
19169     # . epilogue
19170     89/<- %esp 5/r32/ebp
19171     5d/pop-to-ebp
19172     c3/return
19173 
19174 size-of-type-id:  # t: type-id -> result/eax: int
19175     # . prologue
19176     55/push-ebp
19177     89/<- %ebp 4/r32/esp
19178     # . save registers
19179     51/push-ecx
19180     # var out/ecx: (handle typeinfo)
19181     68/push 0/imm32
19182     68/push 0/imm32
19183     89/<- %ecx 4/r32/esp
19184     # eax = t
19185     8b/-> *(ebp+8) 0/r32/eax
19186     # if t is a literal, return 0
19187     3d/compare-eax-and 0/imm32
19188     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
19189     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
19190     3d/compare-eax-and 8/imm32/byte
19191     {
19192       75/jump-if-!= break/disp8
19193       b8/copy-to-eax 4/imm32
19194       eb/jump $size-of-type-id:end/disp8
19195     }
19196     # if t is a handle, return 8
19197     3d/compare-eax-and 4/imm32/handle
19198     {
19199       75/jump-if-!= break/disp8
19200       b8/copy-to-eax 8/imm32
19201       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
19202     }
19203     # if t is a slice, return 8
19204     3d/compare-eax-and 0xc/imm32/slice
19205     {
19206       75/jump-if-!= break/disp8
19207       b8/copy-to-eax 8/imm32
19208       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
19209     }
19210     # if t is a user-defined type, return its size
19211     # TODO: support non-atom type
19212     (find-typeinfo %eax %ecx)
19213     {
19214       81 7/subop/compare *ecx 0/imm32
19215       74/jump-if-= break/disp8
19216 $size-of-type-id:user-defined:
19217       (lookup *ecx *(ecx+4))  # => eax
19218       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
19219       eb/jump $size-of-type-id:end/disp8
19220     }
19221     # otherwise return the word size
19222     b8/copy-to-eax 4/imm32
19223 $size-of-type-id:end:
19224     # . reclaim locals
19225     81 0/subop/add %esp 8/imm32
19226     # . restore registers
19227     59/pop-to-ecx
19228     # . epilogue
19229     89/<- %esp 5/r32/ebp
19230     5d/pop-to-ebp
19231     c3/return
19232 
19233 # Minor violation of our type system since it returns an addr. But we could
19234 # replace it with a handle some time.
19235 # Returns null if t is an atom.
19236 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
19237     # . prologue
19238     55/push-ebp
19239     89/<- %ebp 4/r32/esp
19240     # . save registers
19241     51/push-ecx
19242     # eax = 0
19243     b8/copy-to-eax 0/imm32
19244     # ecx = t
19245     8b/-> *(ebp+8) 1/r32/ecx
19246 $type-tail:check-atom:
19247     # if t->is-atom? return 0
19248     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19249     0f 85/jump-if-!= $type-tail:end/disp32
19250     # var tail = t->right
19251     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19252     89/<- %ecx 0/r32/eax
19253 $type-tail:check-singleton:
19254     # if (tail->right == 0) return tail->left
19255     {
19256       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
19257       75/jump-if-!= break/disp8
19258       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19259       e9/jump $type-tail:end/disp32
19260     }
19261     # if tail->right->left is an array-capacity, return tail->left
19262     {
19263 $type-tail:check-array-capacity:
19264       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19265       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
19266       75/jump-if-!= break/disp8
19267 $type-tail:check-array-capacity-1:
19268       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19269       3d/compare-eax-and 0/imm32
19270       74/jump-if-= break/disp8
19271 $type-tail:check-array-capacity-2:
19272       (is-simple-mu-type? %eax 9)  # array-capacity => eax
19273       3d/compare-eax-and 0/imm32/false
19274       74/jump-if-= break/disp8
19275 $type-tail:array-capacity:
19276       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19277       eb/jump $type-tail:end/disp8
19278     }
19279 $type-tail:check-compound-left:
19280     # if !tail->left->is-atom? return tail->left
19281     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19282     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
19283     74/jump-if-= $type-tail:end/disp8
19284 $type-tail:return-tail:
19285     # return tail
19286     89/<- %eax 1/r32/ecx
19287 $type-tail:end:
19288     # . restore registers
19289     59/pop-to-ecx
19290     # . epilogue
19291     89/<- %esp 5/r32/ebp
19292     5d/pop-to-ebp
19293     c3/return
19294 
19295 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
19296     # . prologue
19297     55/push-ebp
19298     89/<- %ebp 4/r32/esp
19299     # . save registers
19300     51/push-ecx
19301     52/push-edx
19302     53/push-ebx
19303     # ecx = a
19304     8b/-> *(ebp+8) 1/r32/ecx
19305     # edx = b
19306     8b/-> *(ebp+0xc) 2/r32/edx
19307 $type-equal?:compare-addr:
19308     # if (a == b) return true
19309     8b/-> %ecx 0/r32/eax  # Var-type
19310     39/compare %edx 0/r32/eax  # Var-type
19311     b8/copy-to-eax 1/imm32/true
19312     0f 84/jump-if-= $type-equal?:end/disp32
19313 $type-equal?:compare-null-a:
19314     # if (a == 0) return false
19315     b8/copy-to-eax 0/imm32/false
19316     81 7/subop/compare %ecx 0/imm32
19317     0f 84/jump-if-= $type-equal?:end/disp32
19318 $type-equal?:compare-null-b:
19319     # if (b == 0) return false
19320     81 7/subop/compare %edx 0/imm32
19321     0f 84/jump-if-= $type-equal?:end/disp32
19322 $type-equal?:compare-atom-state:
19323     # if (a->is-atom? != b->is-atom?) return false
19324     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
19325     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
19326     b8/copy-to-eax 0/imm32/false
19327     0f 85/jump-if-!= $type-equal?:end/disp32
19328     # if a->is-atom? return (a->value == b->value)
19329     {
19330 $type-equal?:check-atom:
19331       81 7/subop/compare %ebx 0/imm32/false
19332       74/jump-if-= break/disp8
19333 $type-equal?:is-atom:
19334       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
19335       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
19336       0f 94/set-if-= %al
19337       81 4/subop/and %eax 0xff/imm32
19338       e9/jump $type-equal?:end/disp32
19339     }
19340 $type-equal?:check-left:
19341     # if (!type-equal?(a->left, b->left)) return false
19342     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19343     89/<- %ebx 0/r32/eax
19344     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
19345     (type-equal? %eax %ebx)  # => eax
19346     3d/compare-eax-and 0/imm32/false
19347     74/jump-if-= $type-equal?:end/disp8
19348 $type-equal?:check-right:
19349     # return type-equal?(a->right, b->right)
19350     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19351     89/<- %ebx 0/r32/eax
19352     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
19353     (type-equal? %eax %ebx)  # => eax
19354 $type-equal?:end:
19355     # . restore registers
19356     5b/pop-to-ebx
19357     5a/pop-to-edx
19358     59/pop-to-ecx
19359     # . epilogue
19360     89/<- %esp 5/r32/ebp
19361     5d/pop-to-ebp
19362     c3/return
19363 
19364 #######################################################
19365 # Code-generation
19366 #######################################################
19367 
19368 == data
19369 
19370 # Global state added to each var record when performing code-generation.
19371 Curr-local-stack-offset:  # (addr int)
19372     0/imm32
19373 
19374 == code
19375 
19376 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
19377     # . prologue
19378     55/push-ebp
19379     89/<- %ebp 4/r32/esp
19380     # . save registers
19381     50/push-eax
19382     # var curr/eax: (addr function) = *Program->functions
19383     (lookup *_Program-functions *_Program-functions->payload)  # => eax
19384     {
19385       # if (curr == null) break
19386       3d/compare-eax-and 0/imm32
19387       0f 84/jump-if-= break/disp32
19388       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
19389       # curr = lookup(curr->next)
19390       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
19391       e9/jump loop/disp32
19392     }
19393 $emit-subx:end:
19394     # . restore registers
19395     58/pop-to-eax
19396     # . epilogue
19397     89/<- %esp 5/r32/ebp
19398     5d/pop-to-ebp
19399     c3/return
19400 
19401 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19402     # . prologue
19403     55/push-ebp
19404     89/<- %ebp 4/r32/esp
19405     # some preprocessing
19406     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
19407     # . save registers
19408     50/push-eax
19409     51/push-ecx
19410     52/push-edx
19411     # initialize some global state
19412     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
19413     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
19414     # ecx = f
19415     8b/-> *(ebp+0xc) 1/r32/ecx
19416     # var vars/edx: (stack (addr var) 256)
19417     81 5/subop/subtract %esp 0xc00/imm32
19418     68/push 0xc00/imm32/size
19419     68/push 0/imm32/top
19420     89/<- %edx 4/r32/esp
19421     # var name/eax: (addr array byte) = lookup(f->name)
19422     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
19423     #
19424     (write-buffered *(ebp+8) %eax)
19425     (write-buffered *(ebp+8) ":\n")
19426     (emit-subx-prologue *(ebp+8))
19427     # var body/eax: (addr block) = lookup(f->body)
19428     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
19429     #
19430     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19431     (emit-subx-epilogue *(ebp+8))
19432     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
19433     # been cleaned up
19434 $emit-subx-function:end:
19435     # . reclaim locals
19436     81 0/subop/add %esp 0xc08/imm32
19437     # . restore registers
19438     5a/pop-to-edx
19439     59/pop-to-ecx
19440     58/pop-to-eax
19441     # . epilogue
19442     89/<- %esp 5/r32/ebp
19443     5d/pop-to-ebp
19444     c3/return
19445 
19446 populate-mu-type-offsets-in-inouts:  # f: (addr function)
19447     # . prologue
19448     55/push-ebp
19449     89/<- %ebp 4/r32/esp
19450     # . save registers
19451     50/push-eax
19452     51/push-ecx
19453     52/push-edx
19454     53/push-ebx
19455     57/push-edi
19456     # var next-offset/edx: int = 8
19457     ba/copy-to-edx 8/imm32
19458     # var curr/ecx: (addr list var) = lookup(f->inouts)
19459     8b/-> *(ebp+8) 1/r32/ecx
19460     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
19461     89/<- %ecx 0/r32/eax
19462     {
19463 $populate-mu-type-offsets-in-inouts:loop:
19464       81 7/subop/compare %ecx 0/imm32
19465       74/jump-if-= break/disp8
19466       # var v/ebx: (addr var) = lookup(curr->value)
19467       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19468       89/<- %ebx 0/r32/eax
19469 #?       (lookup *ebx *(ebx+4))
19470 #?       (write-buffered Stderr "setting offset of fn inout ")
19471 #?       (write-buffered Stderr %eax)
19472 #?       (write-buffered Stderr "@")
19473 #?       (write-int32-hex-buffered Stderr %ebx)
19474 #?       (write-buffered Stderr " to ")
19475 #?       (write-int32-hex-buffered Stderr %edx)
19476 #?       (write-buffered Stderr Newline)
19477 #?       (flush Stderr)
19478       # v->offset = next-offset
19479       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
19480       # next-offset += size-of(v)
19481       (size-of %ebx)  # => eax
19482       01/add-to %edx 0/r32/eax
19483       # curr = lookup(curr->next)
19484       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
19485       89/<- %ecx 0/r32/eax
19486       #
19487       eb/jump loop/disp8
19488     }
19489 $populate-mu-type-offsets-in-inouts:end:
19490     # . restore registers
19491     5f/pop-to-edi
19492     5b/pop-to-ebx
19493     5a/pop-to-edx
19494     59/pop-to-ecx
19495     58/pop-to-eax
19496     # . epilogue
19497     89/<- %esp 5/r32/ebp
19498     5d/pop-to-ebp
19499     c3/return
19500 
19501 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)
19502     # . prologue
19503     55/push-ebp
19504     89/<- %ebp 4/r32/esp
19505     # . save registers
19506     50/push-eax
19507     51/push-ecx
19508     53/push-ebx
19509     56/push-esi
19510     # esi = stmts
19511     8b/-> *(ebp+0xc) 6/r32/esi
19512     #
19513     {
19514 $emit-subx-stmt-list:loop:
19515       81 7/subop/compare %esi 0/imm32
19516       0f 84/jump-if-= break/disp32
19517       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
19518       (lookup *esi *(esi+4))  # List-value List-value => eax
19519       89/<- %ecx 0/r32/eax
19520       {
19521 $emit-subx-stmt-list:check-for-block:
19522         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
19523         75/jump-if-!= break/disp8
19524 $emit-subx-stmt-list:block:
19525         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19526       }
19527       {
19528 $emit-subx-stmt-list:check-for-stmt:
19529         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
19530         0f 85/jump-if-!= break/disp32
19531 $emit-subx-stmt-list:stmt1:
19532         {
19533           (is-mu-branch? %ecx)  # => eax
19534           3d/compare-eax-and 0/imm32/false
19535           0f 84/jump-if-= break/disp32
19536 $emit-subx-stmt-list:branch-stmt:
19537 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
19562 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
19589 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
19605 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
19643 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
19662         }
19663 $emit-subx-stmt-list:1-to-1:
19664         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
19665         e9/jump $emit-subx-stmt-list:continue/disp32
19666       }
19667       {
19668 $emit-subx-stmt-list:check-for-var-def:
19669         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
19670         75/jump-if-!= break/disp8
19671 $emit-subx-stmt-list:var-def:
19672         (emit-subx-var-def *(ebp+8) %ecx)
19673         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
19674         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
19675         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
19676         #
19677         eb/jump $emit-subx-stmt-list:continue/disp8
19678       }
19679       {
19680 $emit-subx-stmt-list:check-for-reg-var-def:
19681         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
19682         0f 85/jump-if-!= break/disp32
19683 $emit-subx-stmt-list:reg-var-def:
19684         # TODO: ensure that there's exactly one output
19685         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19686         # emit the instruction as usual
19687         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
19688         #
19689         eb/jump $emit-subx-stmt-list:continue/disp8
19690       }
19691 $emit-subx-stmt-list:continue:
19692       # TODO: raise an error on unrecognized Stmt-tag
19693       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
19694       89/<- %esi 0/r32/eax
19695       e9/jump loop/disp32
19696     }
19697 $emit-subx-stmt-list:emit-cleanup:
19698     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
19699 $emit-subx-stmt-list:clean-up:
19700     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
19701     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
19702 $emit-subx-stmt-list:end:
19703     # . restore registers
19704     5e/pop-to-esi
19705     5b/pop-to-ebx
19706     59/pop-to-ecx
19707     58/pop-to-eax
19708     # . epilogue
19709     89/<- %esp 5/r32/ebp
19710     5d/pop-to-ebp
19711     c3/return
19712 
19713 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
19714 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)
19715     # . prologue
19716     55/push-ebp
19717     89/<- %ebp 4/r32/esp
19718     # . save registers
19719     50/push-eax
19720     51/push-ecx
19721     52/push-edx
19722     # ecx = stmt
19723     8b/-> *(ebp+0xc) 1/r32/ecx
19724     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
19725     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
19726     # TODO: assert !sv->is-deref?
19727     # var v/ecx: (addr var) = lookup(sv->value)
19728     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19729     89/<- %ecx 0/r32/eax
19730     # v->block-depth = *Curr-block-depth
19731     8b/-> *Curr-block-depth 0/r32/eax
19732     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19733 #?     (write-buffered Stderr "var ")
19734 #?     (lookup *ecx *(ecx+4))
19735 #?     (write-buffered Stderr %eax)
19736 #?     (write-buffered Stderr " at depth ")
19737 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
19738 #?     (write-buffered Stderr Newline)
19739 #?     (flush Stderr)
19740     # ensure that v is in a register
19741     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
19742     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
19743     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
19744     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
19745     89/<- %edx 0/r32/eax
19746     3d/compare-eax-and 0/imm32/false
19747     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
19748     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
19749     89/<- %edx 0/r32/eax
19750     # check emit-spill?
19751     3d/compare-eax-and 0/imm32/false
19752     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
19753     # TODO: assert(size-of(output) == 4)
19754     # *Curr-local-stack-offset -= 4
19755     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
19756     # emit spill
19757     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19758     (emit-push-register *(ebp+8) %eax)
19759 $push-output-and-maybe-emit-spill:push:
19760     8b/-> *(ebp+0xc) 1/r32/ecx
19761     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
19762     # push(vars, {sv->value, emit-spill?})
19763     (push *(ebp+0x10) *eax)  # Stmt-var-value
19764     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
19765     (push *(ebp+0x10) %edx)
19766 $push-output-and-maybe-emit-spill:end:
19767     # . restore registers
19768     5a/pop-to-edx
19769     59/pop-to-ecx
19770     58/pop-to-eax
19771     # . epilogue
19772     89/<- %esp 5/r32/ebp
19773     5d/pop-to-ebp
19774     c3/return
19775 
19776 $push-output-and-maybe-emit-spill:abort:
19777     # error("var '" var->name "' initialized from an instruction must live in a register\n")
19778     (write-buffered *(ebp+0x1c) "var '")
19779     (write-buffered *(ebp+0x1c) *eax)  # Var-name
19780     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
19781     (flush *(ebp+0x1c))
19782     (stop *(ebp+0x20) 1)
19783     # never gets here
19784 
19785 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
19786     # . prologue
19787     55/push-ebp
19788     89/<- %ebp 4/r32/esp
19789     # . save registers
19790     50/push-eax
19791     51/push-ecx
19792     # ecx = stmt
19793     8b/-> *(ebp+0xc) 1/r32/ecx
19794     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
19795     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19796     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19797     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19798     # clean up until target block
19799     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
19800     # emit jump to target block
19801     (emit-indent *(ebp+8) *Curr-block-depth)
19802     (write-buffered *(ebp+8) "e9/jump ")
19803     (write-buffered *(ebp+8) %eax)
19804     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
19805     (string-starts-with? %eax "break")
19806     3d/compare-eax-and 0/imm32/false
19807     {
19808       74/jump-if-= break/disp8
19809       (write-buffered *(ebp+8) ":break/disp32\n")
19810       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
19811     }
19812     (write-buffered *(ebp+8) ":loop/disp32\n")
19813 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
19814     # . restore registers
19815     59/pop-to-ecx
19816     58/pop-to-eax
19817     # . epilogue
19818     89/<- %esp 5/r32/ebp
19819     5d/pop-to-ebp
19820     c3/return
19821 
19822 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
19823     # pseudocode:
19824     #   for every inout, output in return-stmt, fn->outputs
19825     #     if inout is a literal
19826     #       c7 0/subop/copy %output inout/imm32
19827     #     otherwise
19828     #       8b/-> inout %output
19829     #
19830     # . prologue
19831     55/push-ebp
19832     89/<- %ebp 4/r32/esp
19833     # . save registers
19834     50/push-eax
19835     51/push-ecx
19836     56/push-esi
19837     57/push-edi
19838     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
19839     8b/-> *(ebp+0xc) 0/r32/eax
19840     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19841     89/<- %esi 0/r32/eax
19842     # var curr-output/edi: (addr list var) = fn->outputs
19843     8b/-> *(ebp+0x10) 0/r32/eax
19844     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
19845     89/<- %edi 0/r32/eax
19846     {
19847 $emit-outputs:loop:
19848       81 7/subop/compare %esi 0/imm32
19849       0f 84/jump-if-= break/disp32
19850       # emit copy to output register
19851       # var curr-var/ecx = lookup(curr-inout->value)
19852       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19853       89/<- %ecx 0/r32/eax
19854       # if curr-var is a literal, emit copy of a literal to the output
19855       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19856       (is-simple-mu-type? %eax 0)  # literal => eax
19857       {
19858         3d/compare-eax-and 0/imm32/false
19859         0f 84/jump-if-= break/disp32
19860         (emit-indent *(ebp+8) *Curr-block-depth)
19861         (write-buffered *(ebp+8) "c7 0/subop/copy %")
19862         (lookup *edi *(edi+4))  # List-value List-value => eax
19863         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19864         (write-buffered *(ebp+8) %eax)
19865         (write-buffered *(ebp+8) " ")
19866         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
19867         (write-buffered *(ebp+8) %eax)
19868         (write-buffered *(ebp+8) "/imm32\n")
19869         e9/jump $emit-outputs:continue/disp32
19870       }
19871       # if the non-literal is a register starting with "x", emit a floating-point copy
19872       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19873       {
19874         3d/compare-eax-and 0/imm32
19875         0f 84/jump-if-= break/disp32
19876         8a/copy-byte *(eax+4) 0/r32/AL
19877         81 4/subop/and %eax 0xff/imm32
19878         3d/compare-eax-and 0x78/imm32/x
19879         0f 85/jump-if-!= break/disp32
19880         (emit-indent *(ebp+8) *Curr-block-depth)
19881         (write-buffered *(ebp+8) "f3 0f 10/->")
19882         (emit-subx-var-as-rm32 *(ebp+8) %esi)
19883         (write-buffered *(ebp+8) " ")
19884         (lookup *edi *(edi+4))  # List-value List-value => eax
19885         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19886         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
19887         (write-int32-hex-buffered *(ebp+8) *eax)
19888         (write-buffered *(ebp+8) "/x32\n")
19889         e9/jump $emit-outputs:continue/disp32
19890       }
19891       # otherwise emit an integer copy
19892       (emit-indent *(ebp+8) *Curr-block-depth)
19893       (write-buffered *(ebp+8) "8b/->")
19894       (emit-subx-var-as-rm32 *(ebp+8) %esi)
19895       (write-buffered *(ebp+8) " ")
19896       (lookup *edi *(edi+4))  # List-value List-value => eax
19897       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19898       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
19899       (write-int32-hex-buffered *(ebp+8) *eax)
19900       (write-buffered *(ebp+8) "/r32\n")
19901 $emit-outputs:continue:
19902       # curr-inout = curr-inout->next
19903       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19904       89/<- %esi 0/r32/eax
19905       # curr-output = curr-output->next
19906       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
19907       89/<- %edi 0/r32/eax
19908       #
19909       e9/jump loop/disp32
19910     }
19911 $emit-outputs:end:
19912     # . restore registers
19913     5f/pop-to-edi
19914     5e/pop-to-esi
19915     59/pop-to-ecx
19916     58/pop-to-eax
19917     # . epilogue
19918     89/<- %esp 5/r32/ebp
19919     5d/pop-to-ebp
19920     c3/return
19921 
19922 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
19923     # . prologue
19924     55/push-ebp
19925     89/<- %ebp 4/r32/esp
19926     # . save registers
19927     51/push-ecx
19928     # ecx = lookup(stmt->operation)
19929     8b/-> *(ebp+8) 1/r32/ecx
19930     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
19931     89/<- %ecx 0/r32/eax
19932     # if (stmt->operation starts with "loop") return true
19933     (string-starts-with? %ecx "loop")  # => eax
19934     3d/compare-eax-and 0/imm32/false
19935     75/jump-if-not-equal $is-mu-branch?:end/disp8
19936     # if (stmt->operation starts with "break") return true
19937     (string-starts-with? %ecx "break")  # => eax
19938     3d/compare-eax-and 0/imm32/false
19939     75/jump-if-not-equal $is-mu-branch?:end/disp8
19940     # otherwise return (stmt->operation starts with "return")
19941     (string-starts-with? %ecx "return")  # => eax
19942 $is-mu-branch?:end:
19943     # . restore registers
19944     59/pop-to-ecx
19945     # . epilogue
19946     89/<- %esp 5/r32/ebp
19947     5d/pop-to-ebp
19948     c3/return
19949 
19950 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
19951     # . prologue
19952     55/push-ebp
19953     89/<- %ebp 4/r32/esp
19954     # . save registers
19955     50/push-eax
19956     # eax = stmt
19957     8b/-> *(ebp+0xc) 0/r32/eax
19958     #
19959     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
19960     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
19961     (emit-indent *(ebp+8) *Curr-block-depth)
19962     (lookup *eax *(eax+4))  # => eax
19963     (write-buffered *(ebp+8) %eax)
19964     (write-buffered *(ebp+8) " break/disp32\n")
19965 $emit-reverse-break:end:
19966     # . restore registers
19967     58/pop-to-eax
19968     # . epilogue
19969     89/<- %esp 5/r32/ebp
19970     5d/pop-to-ebp
19971     c3/return
19972 
19973 == data
19974 
19975 # Table from Mu branch instructions to the reverse SubX opcodes for them.
19976 Reverse-branch:  # (table (handle array byte) (handle array byte))
19977   # a table is a stream
19978   0x1c0/imm32/write
19979   0/imm32/read
19980   0x1c0/imm32/size
19981   # data
19982   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
19983   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
19984   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
19985   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
19986   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
19987   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
19988   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
19989   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
19990   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
19991   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
19992   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
19993   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
19994   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
19995   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
19996   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
19997   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
19998   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
19999   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
20000   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
20001   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
20002   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
20003   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
20004   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
20005   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
20006   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
20007   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
20008   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
20009   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
20010 
20011 == code
20012 
20013 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
20014     # . prologue
20015     55/push-ebp
20016     89/<- %ebp 4/r32/esp
20017     # . save registers
20018     50/push-eax
20019     51/push-ecx
20020     52/push-edx
20021     53/push-ebx
20022     56/push-esi
20023     # ecx = vars
20024     8b/-> *(ebp+0xc) 1/r32/ecx
20025     # var eax: int = vars->top
20026     8b/-> *ecx 0/r32/eax
20027     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
20028     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
20029     # var min/ecx: (addr handle var) = vars->data
20030     8d/copy-address *(ecx+8) 1/r32/ecx
20031     # edx = depth
20032     8b/-> *(ebp+0x10) 2/r32/edx
20033     {
20034 $emit-unconditional-jump-to-depth:loop:
20035       # if (curr < min) break
20036       39/compare %esi 1/r32/ecx
20037       0f 82/jump-if-addr< break/disp32
20038       # var v/ebx: (addr var) = lookup(*curr)
20039       (lookup *esi *(esi+4))  # => eax
20040       89/<- %ebx 0/r32/eax
20041       # if (v->block-depth < until-block-depth) break
20042       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
20043       0f 8c/jump-if-< break/disp32
20044       {
20045 $emit-unconditional-jump-to-depth:check:
20046         # if v->block-depth != until-block-depth, continue
20047         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
20048         0f 85/jump-if-!= break/disp32
20049 $emit-unconditional-jump-to-depth:depth-found:
20050         # if v is not a literal, continue
20051         (size-of %ebx)  # => eax
20052         3d/compare-eax-and 0/imm32
20053         0f 85/jump-if-!= break/disp32
20054 $emit-unconditional-jump-to-depth:label-found:
20055         # emit unconditional jump, then return
20056         (emit-indent *(ebp+8) *Curr-block-depth)
20057         (write-buffered *(ebp+8) "e9/jump ")
20058         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
20059         (write-buffered *(ebp+8) %eax)
20060         (write-buffered *(ebp+8) ":")
20061         (write-buffered *(ebp+8) *(ebp+0x14))
20062         (write-buffered *(ebp+8) "/disp32\n")
20063         eb/jump $emit-unconditional-jump-to-depth:end/disp8
20064       }
20065       # curr -= 12
20066       81 5/subop/subtract %esi 0xc/imm32
20067       e9/jump loop/disp32
20068     }
20069     # TODO: error if no label at 'depth' was found
20070 $emit-unconditional-jump-to-depth:end:
20071     # . restore registers
20072     5e/pop-to-esi
20073     5b/pop-to-ebx
20074     5a/pop-to-edx
20075     59/pop-to-ecx
20076     58/pop-to-eax
20077     # . epilogue
20078     89/<- %esp 5/r32/ebp
20079     5d/pop-to-ebp
20080     c3/return
20081 
20082 # emit clean-up code for 'vars' until some block depth
20083 # doesn't actually modify 'vars' so we need traverse manually inside the stack
20084 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
20085     # . prologue
20086     55/push-ebp
20087     89/<- %ebp 4/r32/esp
20088     # . save registers
20089     50/push-eax
20090     51/push-ecx
20091     52/push-edx
20092     53/push-ebx
20093     56/push-esi
20094 #?     (write-buffered Stderr "--- cleanup\n")
20095 #?     (flush Stderr)
20096     # ecx = vars
20097     8b/-> *(ebp+0xc) 1/r32/ecx
20098     # var esi: int = vars->top
20099     8b/-> *ecx 6/r32/esi
20100     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
20101     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
20102     # var min/ecx: (addr handle var) = vars->data
20103     81 0/subop/add %ecx 8/imm32
20104     # edx = until-block-depth
20105     8b/-> *(ebp+0x10) 2/r32/edx
20106     {
20107 $emit-cleanup-code-until-depth:loop:
20108       # if (curr < min) break
20109       39/compare %esi 1/r32/ecx
20110       0f 82/jump-if-addr< break/disp32
20111       # var v/ebx: (addr var) = lookup(*curr)
20112       (lookup *esi *(esi+4))  # => eax
20113       89/<- %ebx 0/r32/eax
20114 #?       (lookup *ebx *(ebx+4))  # Var-name
20115 #?       (write-buffered Stderr "var ")
20116 #?       (write-buffered Stderr %eax)
20117 #?       (write-buffered Stderr Newline)
20118 #?       (flush Stderr)
20119       # if (v->block-depth < until-block-depth) break
20120       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
20121       0f 8c/jump-if-< break/disp32
20122       # if v is in a register
20123       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
20124       {
20125         0f 84/jump-if-= break/disp32
20126         {
20127 $emit-cleanup-code-until-depth:check-for-previous-spill:
20128           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
20129           3d/compare-eax-and 0/imm32/false
20130           74/jump-if-= break/disp8
20131 $emit-cleanup-code-until-depth:reclaim-var-in-register:
20132           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
20133           (emit-pop-register *(ebp+8) %eax)
20134         }
20135         eb/jump $emit-cleanup-code-until-depth:continue/disp8
20136       }
20137       # otherwise v is on the stack
20138       {
20139         75/jump-if-!= break/disp8
20140 $emit-cleanup-code-until-depth:var-on-stack:
20141         (size-of %ebx)  # => eax
20142         # don't emit code for labels
20143         3d/compare-eax-and 0/imm32
20144         74/jump-if-= break/disp8
20145 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
20146         (emit-indent *(ebp+8) *Curr-block-depth)
20147         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
20148         (write-int32-hex-buffered *(ebp+8) %eax)
20149         (write-buffered *(ebp+8) "/imm32\n")
20150       }
20151 $emit-cleanup-code-until-depth:continue:
20152       # curr -= 12
20153       81 5/subop/subtract %esi 0xc/imm32
20154       e9/jump loop/disp32
20155     }
20156 $emit-cleanup-code-until-depth:end:
20157     # . restore registers
20158     5e/pop-to-esi
20159     5b/pop-to-ebx
20160     5a/pop-to-edx
20161     59/pop-to-ecx
20162     58/pop-to-eax
20163     # . epilogue
20164     89/<- %esp 5/r32/ebp
20165     5d/pop-to-ebp
20166     c3/return
20167 
20168 # emit clean-up code for 'vars' that don't conflict with output registers
20169 # doesn't actually modify 'vars' so we need traverse manually inside the stack
20170 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
20171     # . prologue
20172     55/push-ebp
20173     89/<- %ebp 4/r32/esp
20174     # . save registers
20175     50/push-eax
20176     51/push-ecx
20177     52/push-edx
20178     53/push-ebx
20179     56/push-esi
20180     57/push-edi
20181     # ecx = vars
20182     8b/-> *(ebp+0xc) 1/r32/ecx
20183     # var esi: int = vars->top
20184     8b/-> *ecx 6/r32/esi
20185     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
20186     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
20187     # var min/ecx: (addr handle var) = vars->data
20188     81 0/subop/add %ecx 8/imm32
20189     {
20190 $emit-cleanup-code-for-non-outputs:loop:
20191       # if (curr < min) break
20192       39/compare %esi 1/r32/ecx
20193       0f 82/jump-if-addr< break/disp32
20194       # var v/ebx: (addr var) = lookup(*curr)
20195       (lookup *esi *(esi+4))  # => eax
20196       89/<- %ebx 0/r32/eax
20197       # if v is in a register
20198       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
20199       {
20200         0f 84/jump-if-= break/disp32
20201         {
20202 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
20203           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
20204           3d/compare-eax-and 0/imm32/false
20205           0f 84/jump-if-= break/disp32
20206 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
20207           # var reg/edi: (addr array name) = v->register
20208           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
20209           89/<- %edi 0/r32/eax
20210           # if reg is not in function outputs, emit a pop
20211           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
20212           3d/compare-eax-and 0/imm32/false
20213           {
20214             75/jump-if-!= break/disp8
20215             (emit-pop-register *(ebp+8) %edi)
20216             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
20217           }
20218           # otherwise just drop it from the stack
20219           (emit-indent *(ebp+8) *Curr-block-depth)
20220           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
20221         }
20222 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
20223         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
20224       }
20225       # otherwise v is on the stack
20226       {
20227         75/jump-if-!= break/disp8
20228 $emit-cleanup-code-for-non-outputs:var-on-stack:
20229         (size-of %ebx)  # => eax
20230         # don't emit code for labels
20231         3d/compare-eax-and 0/imm32
20232         74/jump-if-= break/disp8
20233 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
20234         (emit-indent *(ebp+8) *Curr-block-depth)
20235         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
20236         (write-int32-hex-buffered *(ebp+8) %eax)
20237         (write-buffered *(ebp+8) "/imm32\n")
20238       }
20239 $emit-cleanup-code-for-non-outputs:continue:
20240       # curr -= 12
20241       81 5/subop/subtract %esi 0xc/imm32
20242       e9/jump loop/disp32
20243     }
20244 $emit-cleanup-code-for-non-outputs:end:
20245     # . restore registers
20246     5f/pop-to-edi
20247     5e/pop-to-esi
20248     5b/pop-to-ebx
20249     5a/pop-to-edx
20250     59/pop-to-ecx
20251     58/pop-to-eax
20252     # . epilogue
20253     89/<- %esp 5/r32/ebp
20254     5d/pop-to-ebp
20255     c3/return
20256 
20257 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
20258     # . prologue
20259     55/push-ebp
20260     89/<- %ebp 4/r32/esp
20261     # eax = reg
20262     8b/-> *(ebp+0xc) 0/r32/eax
20263     # var prefix/eax: byte = reg->data[0]
20264     8a/copy-byte *(eax+4) 0/r32/AL
20265     81 4/subop/and %eax 0xff/imm32
20266     # if (prefix == 'x') push xmm register
20267     {
20268       3d/compare-eax-and 0x78/imm32/x
20269       0f 85/jump-if-!= break/disp32
20270       # TODO validate register
20271       (emit-indent *(ebp+8) *Curr-block-depth)
20272       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
20273       (emit-indent *(ebp+8) *Curr-block-depth)
20274       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
20275       # var prefix/eax: byte = reg->data[3]
20276       8b/-> *(ebp+0xc) 0/r32/eax
20277       8a/copy-byte *(eax+7) 0/r32/AL
20278       81 4/subop/and %eax 0xff/imm32
20279       (write-byte-buffered *(ebp+8) %eax)
20280       (write-buffered *(ebp+8) "/x32\n")
20281       e9/jump $emit-push-register:end/disp32
20282     }
20283     # otherwise push gp register
20284     (emit-indent *(ebp+8) *Curr-block-depth)
20285     (write-buffered *(ebp+8) "ff 6/subop/push %")
20286     (write-buffered *(ebp+8) *(ebp+0xc))
20287     (write-buffered *(ebp+8) Newline)
20288 $emit-push-register:end:
20289     # . epilogue
20290     89/<- %esp 5/r32/ebp
20291     5d/pop-to-ebp
20292     c3/return
20293 
20294 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
20295     # . prologue
20296     55/push-ebp
20297     89/<- %ebp 4/r32/esp
20298     # . save registers
20299     50/push-eax
20300     # eax = reg
20301     8b/-> *(ebp+0xc) 0/r32/eax
20302     # var prefix/eax: byte = reg->data[0]
20303     8a/copy-byte *(eax+4) 0/r32/AL
20304     81 4/subop/and %eax 0xff/imm32
20305     # if (prefix == 'x') pop to xmm register
20306     {
20307       3d/compare-eax-and 0x78/imm32/x
20308       0f 85/jump-if-!= break/disp32
20309       # TODO validate register
20310       (emit-indent *(ebp+8) *Curr-block-depth)
20311       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
20312       # var prefix/eax: byte = reg->data[3]
20313       8b/-> *(ebp+0xc) 0/r32/eax
20314       8a/copy-byte *(eax+7) 0/r32/AL
20315       81 4/subop/and %eax 0xff/imm32
20316       (write-byte-buffered *(ebp+8) %eax)
20317       (write-buffered *(ebp+8) "/x32\n")
20318       (emit-indent *(ebp+8) *Curr-block-depth)
20319       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
20320       e9/jump $emit-pop-register:end/disp32
20321     }
20322     # otherwise pop to gp register
20323     (emit-indent *(ebp+8) *Curr-block-depth)
20324     (write-buffered *(ebp+8) "8f 0/subop/pop %")
20325     (write-buffered *(ebp+8) *(ebp+0xc))
20326     (write-buffered *(ebp+8) Newline)
20327 $emit-pop-register:end:
20328     # . restore registers
20329     58/pop-to-eax
20330     # . epilogue
20331     89/<- %esp 5/r32/ebp
20332     5d/pop-to-ebp
20333     c3/return
20334 
20335 # emit clean-up code for 'vars' until a given label is encountered
20336 # doesn't actually modify 'vars' so we need traverse manually inside the stack
20337 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
20338     # . prologue
20339     55/push-ebp
20340     89/<- %ebp 4/r32/esp
20341     # . save registers
20342     50/push-eax
20343     51/push-ecx
20344     52/push-edx
20345     53/push-ebx
20346     # ecx = vars
20347     8b/-> *(ebp+0xc) 1/r32/ecx
20348     # var eax: int = vars->top
20349     8b/-> *ecx 0/r32/eax
20350     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
20351     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
20352     # var min/ecx: (addr handle var) = vars->data
20353     81 0/subop/add %ecx 8/imm32
20354     {
20355 $emit-cleanup-code-until-target:loop:
20356       # if (curr < min) break
20357       39/compare %edx 1/r32/ecx
20358       0f 82/jump-if-addr< break/disp32
20359       # var v/ebx: (handle var) = lookup(*curr)
20360       (lookup *edx *(edx+4))  # => eax
20361       89/<- %ebx 0/r32/eax
20362       # if (v->name == until-block-label) break
20363       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
20364       (string-equal? %eax *(ebp+0x10))  # => eax
20365       3d/compare-eax-and 0/imm32/false
20366       0f 85/jump-if-!= break/disp32
20367       # if v is in a register
20368       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
20369       {
20370         0f 84/jump-if-= break/disp32
20371         {
20372 $emit-cleanup-code-until-target:check-for-previous-spill:
20373           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
20374           3d/compare-eax-and 0/imm32/false
20375           74/jump-if-= break/disp8
20376 $emit-cleanup-code-until-target:reclaim-var-in-register:
20377           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
20378           (emit-pop-register *(ebp+8) %eax)
20379         }
20380         eb/jump $emit-cleanup-code-until-target:continue/disp8
20381       }
20382       # otherwise v is on the stack
20383       {
20384         75/jump-if-!= break/disp8
20385 $emit-cleanup-code-until-target:reclaim-var-on-stack:
20386         (size-of %ebx)  # => eax
20387         # don't emit code for labels
20388         3d/compare-eax-and 0/imm32
20389         74/jump-if-= break/disp8
20390         #
20391         (emit-indent *(ebp+8) *Curr-block-depth)
20392         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
20393         (write-int32-hex-buffered *(ebp+8) %eax)
20394         (write-buffered *(ebp+8) "/imm32\n")
20395       }
20396 $emit-cleanup-code-until-target:continue:
20397       # curr -= 12
20398       81 5/subop/subtract %edx 0xc/imm32
20399       e9/jump loop/disp32
20400     }
20401 $emit-cleanup-code-until-target:end:
20402     # . restore registers
20403     5b/pop-to-ebx
20404     5a/pop-to-edx
20405     59/pop-to-ecx
20406     58/pop-to-eax
20407     # . epilogue
20408     89/<- %esp 5/r32/ebp
20409     5d/pop-to-ebp
20410     c3/return
20411 
20412 # update Curr-local-stack-offset assuming vars until some block depth are popped
20413 # doesn't actually modify 'vars', so we need traverse manually inside the stack
20414 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
20415     # . prologue
20416     55/push-ebp
20417     89/<- %ebp 4/r32/esp
20418     # . save registers
20419     50/push-eax
20420     51/push-ecx
20421     52/push-edx
20422     53/push-ebx
20423     56/push-esi
20424     # ecx = vars
20425     8b/-> *(ebp+8) 1/r32/ecx
20426     # var esi: int = vars->top
20427     8b/-> *ecx 6/r32/esi
20428     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
20429     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
20430     # var min/ecx: (addr handle var) = vars->data
20431     81 0/subop/add %ecx 8/imm32
20432     # edx = until-block-depth
20433     8b/-> *(ebp+0xc) 2/r32/edx
20434     {
20435 $clean-up-stack-offset-state:loop:
20436       # if (curr < min) break
20437       39/compare %esi 1/r32/ecx
20438       0f 82/jump-if-addr< break/disp32
20439       # var v/ebx: (addr var) = lookup(*curr)
20440       (lookup *esi *(esi+4))  # => eax
20441       89/<- %ebx 0/r32/eax
20442       # if (v->block-depth < until-block-depth) break
20443       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
20444       0f 8c/jump-if-< break/disp32
20445       # if v is in a register
20446       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
20447       {
20448         0f 84/jump-if-= break/disp32
20449         {
20450 $clean-up-stack-offset-state:check-for-previous-spill:
20451           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
20452           3d/compare-eax-and 0/imm32/false
20453           74/jump-if-= break/disp8
20454 $clean-up-stack-offset-state:reclaim-var-in-register:
20455           81 0/subop/add *Curr-local-stack-offset 4/imm32
20456         }
20457         eb/jump $clean-up-stack-offset-state:continue/disp8
20458       }
20459       # otherwise v is on the stack
20460       {
20461         75/jump-if-!= break/disp8
20462 $clean-up-stack-offset-state:var-on-stack:
20463         (size-of %ebx)  # => eax
20464         01/add-to *Curr-local-stack-offset 0/r32/eax
20465       }
20466 $clean-up-stack-offset-state:continue:
20467       # curr -= 12
20468       81 5/subop/subtract %esi 0xc/imm32
20469       e9/jump loop/disp32
20470     }
20471 $clean-up-stack-offset-state:end:
20472     # . restore registers
20473     5e/pop-to-esi
20474     5b/pop-to-ebx
20475     5a/pop-to-edx
20476     59/pop-to-ecx
20477     58/pop-to-eax
20478     # . epilogue
20479     89/<- %esp 5/r32/ebp
20480     5d/pop-to-ebp
20481     c3/return
20482 
20483 # Return true if there isn't a variable in 'vars' with the same block-depth
20484 # and register as 'v'.
20485 # 'v' is guaranteed not to be within 'vars'.
20486 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
20487     # . prologue
20488     55/push-ebp
20489     89/<- %ebp 4/r32/esp
20490     # . save registers
20491     51/push-ecx
20492     52/push-edx
20493     53/push-ebx
20494     56/push-esi
20495     57/push-edi
20496     # ecx = vars
20497     8b/-> *(ebp+0xc) 1/r32/ecx
20498     # var eax: int = vars->top
20499     8b/-> *ecx 0/r32/eax
20500     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
20501     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
20502     # var min/ecx: (addr handle var) = vars->data
20503     8d/copy-address *(ecx+8) 1/r32/ecx
20504     # var depth/ebx: int = v->block-depth
20505     8b/-> *(ebp+8) 3/r32/ebx
20506     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
20507     # var needle/esi: (addr array byte) = v->register
20508     8b/-> *(ebp+8) 6/r32/esi
20509     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
20510     89/<- %esi 0/r32/eax
20511     {
20512 $not-yet-spilled-this-block?:loop:
20513       # if (curr < min) break
20514       39/compare %edx 1/r32/ecx
20515       0f 82/jump-if-addr< break/disp32
20516       # var cand/edi: (addr var) = lookup(*curr)
20517       (lookup *edx *(edx+4))  # => eax
20518       89/<- %edi 0/r32/eax
20519       # if (cand->block-depth < depth) break
20520       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
20521       0f 8c/jump-if-< break/disp32
20522       # var cand-reg/edi: (array array byte) = cand->reg
20523       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
20524       89/<- %edi 0/r32/eax
20525       # if (cand-reg == null) continue
20526       {
20527 $not-yet-spilled-this-block?:check-reg:
20528         81 7/subop/compare %edi 0/imm32
20529         0f 84/jump-if-= break/disp32
20530         # if (cand-reg == needle) return true
20531         (string-equal? %esi %edi)  # => eax
20532         3d/compare-eax-and 0/imm32/false
20533         74/jump-if-= break/disp8
20534 $not-yet-spilled-this-block?:return-false:
20535         b8/copy-to-eax 0/imm32/false
20536         eb/jump $not-yet-spilled-this-block?:end/disp8
20537       }
20538 $not-yet-spilled-this-block?:continue:
20539       # curr -= 12
20540       81 5/subop/subtract %edx 0xc/imm32
20541       e9/jump loop/disp32
20542     }
20543 $not-yet-spilled-this-block?:return-true:
20544     # return true
20545     b8/copy-to-eax 1/imm32/true
20546 $not-yet-spilled-this-block?:end:
20547     # . restore registers
20548     5f/pop-to-edi
20549     5e/pop-to-esi
20550     5b/pop-to-ebx
20551     5a/pop-to-edx
20552     59/pop-to-ecx
20553     # . epilogue
20554     89/<- %esp 5/r32/ebp
20555     5d/pop-to-ebp
20556     c3/return
20557 
20558 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
20559 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
20560     # . prologue
20561     55/push-ebp
20562     89/<- %ebp 4/r32/esp
20563     # eax = v
20564     8b/-> *(ebp+8) 0/r32/eax
20565     # var reg/eax: (addr array byte) = lookup(v->register)
20566     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20567     # var target/eax: (addr var) = find-register(fn-outputs, reg)
20568     (find-register *(ebp+0x10) %eax)  # => eax
20569     # if (target == 0) return true
20570     {
20571       3d/compare-eax-and 0/imm32
20572       75/jump-if-!= break/disp8
20573       b8/copy-to-eax 1/imm32/true
20574       eb/jump $will-not-write-some-register?:end/disp8
20575     }
20576     # return !assigns-in-stmts?(stmts, target)
20577     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
20578     3d/compare-eax-and 0/imm32/false
20579     # assume: true = 1, so no need to mask with 0x000000ff
20580     0f 94/set-if-= %al
20581 $will-not-write-some-register?:end:
20582     # . epilogue
20583     89/<- %esp 5/r32/ebp
20584     5d/pop-to-ebp
20585     c3/return
20586 
20587 # return fn output with matching register
20588 # always returns false if 'reg' is null
20589 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
20590     # . prologue
20591     55/push-ebp
20592     89/<- %ebp 4/r32/esp
20593     # . save registers
20594     51/push-ecx
20595     # var curr/ecx: (addr list var) = lookup(fn->outputs)
20596     8b/-> *(ebp+8) 1/r32/ecx
20597     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
20598     89/<- %ecx 0/r32/eax
20599     {
20600 $find-register:loop:
20601       # if (curr == 0) break
20602       81 7/subop/compare %ecx 0/imm32
20603       74/jump-if-= break/disp8
20604       # eax = curr->value->register
20605       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20606       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20607       # if (eax == reg) return curr->value
20608 $find-register:compare:
20609       (string-equal? *(ebp+0xc) %eax)  # => eax
20610       {
20611         3d/compare-eax-and 0/imm32/false
20612         74/jump-if-= break/disp8
20613 $find-register:found:
20614         (lookup *ecx *(ecx+4))  # List-value List-value => eax
20615         eb/jump $find-register:end/disp8
20616       }
20617       # curr = lookup(curr->next)
20618       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20619       89/<- %ecx 0/r32/eax
20620       #
20621       eb/jump loop/disp8
20622     }
20623 $find-register:end:
20624     # . restore registers
20625     59/pop-to-ecx
20626     # . epilogue
20627     89/<- %esp 5/r32/ebp
20628     5d/pop-to-ebp
20629     c3/return
20630 
20631 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
20632     # . prologue
20633     55/push-ebp
20634     89/<- %ebp 4/r32/esp
20635     # . save registers
20636     51/push-ecx
20637     # var curr/ecx: (addr list stmt) = stmts
20638     8b/-> *(ebp+8) 1/r32/ecx
20639     {
20640       # if (curr == 0) break
20641       81 7/subop/compare %ecx 0/imm32
20642       74/jump-if-= break/disp8
20643       # if assigns-in-stmt?(curr->value, v) return true
20644       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20645       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
20646       3d/compare-eax-and 0/imm32/false
20647       75/jump-if-!= break/disp8
20648       # curr = lookup(curr->next)
20649       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20650       89/<- %ecx 0/r32/eax
20651       #
20652       eb/jump loop/disp8
20653     }
20654 $assigns-in-stmts?:end:
20655     # . restore registers
20656     59/pop-to-ecx
20657     # . epilogue
20658     89/<- %esp 5/r32/ebp
20659     5d/pop-to-ebp
20660     c3/return
20661 
20662 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
20663     # . prologue
20664     55/push-ebp
20665     89/<- %ebp 4/r32/esp
20666     # . save registers
20667     51/push-ecx
20668     # ecx = stmt
20669     8b/-> *(ebp+8) 1/r32/ecx
20670     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
20671     {
20672       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
20673       75/jump-if-!= break/disp8
20674       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20675       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
20676       eb/jump $assigns-in-stmt?:end/disp8
20677     }
20678     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
20679     {
20680       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
20681       75/jump-if-!= break/disp8
20682       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
20683       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
20684       eb/jump $assigns-in-stmt?:end/disp8
20685     }
20686     # otherwise return false
20687     b8/copy 0/imm32/false
20688 $assigns-in-stmt?:end:
20689     # . restore registers
20690     59/pop-to-ecx
20691     # . epilogue
20692     89/<- %esp 5/r32/ebp
20693     5d/pop-to-ebp
20694     c3/return
20695 
20696 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
20697     # . prologue
20698     55/push-ebp
20699     89/<- %ebp 4/r32/esp
20700     # . save registers
20701     51/push-ecx
20702     # var curr/ecx: (addr stmt-var) = stmt-var
20703     8b/-> *(ebp+8) 1/r32/ecx
20704     {
20705       # if (curr == 0) break
20706       81 7/subop/compare %ecx 0/imm32
20707       74/jump-if-= break/disp8
20708       # eax = lookup(curr->value)
20709       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
20710       # if (eax == v  &&  curr->is-deref? == false) return true
20711       {
20712         39/compare *(ebp+0xc) 0/r32/eax
20713         75/jump-if-!= break/disp8
20714         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
20715         75/jump-if-!= break/disp8
20716         b8/copy-to-eax 1/imm32/true
20717         eb/jump $assigns-in-stmt-vars?:end/disp8
20718       }
20719       # curr = lookup(curr->next)
20720       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
20721       89/<- %ecx 0/r32/eax
20722       #
20723       eb/jump loop/disp8
20724     }
20725 $assigns-in-stmt-vars?:end:
20726     # . restore registers
20727     59/pop-to-ecx
20728     # . epilogue
20729     89/<- %esp 5/r32/ebp
20730     5d/pop-to-ebp
20731     c3/return
20732 
20733 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
20734 # v is guaranteed to be within vars
20735 # 'start' is provided as an optimization, a pointer within vars
20736 # *start == v
20737 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
20738     # . prologue
20739     55/push-ebp
20740     89/<- %ebp 4/r32/esp
20741     # . save registers
20742     51/push-ecx
20743     52/push-edx
20744     53/push-ebx
20745     56/push-esi
20746     57/push-edi
20747     # ecx = v
20748     8b/-> *(ebp+8) 1/r32/ecx
20749     # var reg/edx: (addr array byte) = lookup(v->register)
20750     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
20751     89/<- %edx 0/r32/eax
20752     # var depth/ebx: int = v->block-depth
20753     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
20754     # var min/ecx: (addr handle var) = vars->data
20755     8b/-> *(ebp+0xc) 1/r32/ecx
20756     81 0/subop/add %ecx 8/imm32
20757     # TODO: check that start >= min and start < &vars->data[top]
20758     # TODO: check that *start == v
20759     # var curr/esi: (addr handle var) = start
20760     8b/-> *(ebp+0x10) 6/r32/esi
20761     # curr -= 8
20762     81 5/subop/subtract %esi 8/imm32
20763     {
20764 $same-register-spilled-before?:loop:
20765       # if (curr < min) break
20766       39/compare %esi 1/r32/ecx
20767       0f 82/jump-if-addr< break/disp32
20768       # var x/eax: (addr var) = lookup(*curr)
20769       (lookup *esi *(esi+4))  # => eax
20770       # if (x->block-depth < depth) break
20771       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
20772       0f 8c/jump-if-< break/disp32
20773       # if (x->register == 0) continue
20774       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
20775       74/jump-if-= $same-register-spilled-before?:continue/disp8
20776       # if (x->register == reg) return true
20777       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20778       (string-equal? %eax %edx)  # => eax
20779       3d/compare-eax-and 0/imm32/false
20780       b8/copy-to-eax 1/imm32/true
20781       75/jump-if-!= $same-register-spilled-before?:end/disp8
20782 $same-register-spilled-before?:continue:
20783       # curr -= 8
20784       81 5/subop/subtract %esi 8/imm32
20785       e9/jump loop/disp32
20786     }
20787 $same-register-spilled-before?:false:
20788     b8/copy-to-eax 0/imm32/false
20789 $same-register-spilled-before?:end:
20790     # . restore registers
20791     5f/pop-to-edi
20792     5e/pop-to-esi
20793     5b/pop-to-ebx
20794     5a/pop-to-edx
20795     59/pop-to-ecx
20796     # . epilogue
20797     89/<- %esp 5/r32/ebp
20798     5d/pop-to-ebp
20799     c3/return
20800 
20801 # clean up global state for 'vars' until some block depth (inclusive)
20802 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
20803     # . prologue
20804     55/push-ebp
20805     89/<- %ebp 4/r32/esp
20806     # . save registers
20807     50/push-eax
20808     51/push-ecx
20809     56/push-esi
20810     # esi = vars
20811     8b/-> *(ebp+8) 6/r32/esi
20812     # ecx = until-block-depth
20813     8b/-> *(ebp+0xc) 1/r32/ecx
20814     {
20815 $clean-up-blocks:reclaim-loop:
20816       # if (vars->top <= 0) break
20817       8b/-> *esi 0/r32/eax  # Stack-top
20818       3d/compare-eax-and 0/imm32
20819       0f 8e/jump-if-<= break/disp32
20820       # var v/eax: (addr var) = lookup(vars[vars->top-12])
20821       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
20822       # if (v->block-depth < until-block-depth) break
20823       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
20824       0f 8c/jump-if-< break/disp32
20825       (pop %esi)  # => eax
20826       (pop %esi)  # => eax
20827       (pop %esi)  # => eax
20828       e9/jump loop/disp32
20829     }
20830 $clean-up-blocks:end:
20831     # . restore registers
20832     5e/pop-to-esi
20833     59/pop-to-ecx
20834     58/pop-to-eax
20835     # . epilogue
20836     89/<- %esp 5/r32/ebp
20837     5d/pop-to-ebp
20838     c3/return
20839 
20840 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
20841     # . prologue
20842     55/push-ebp
20843     89/<- %ebp 4/r32/esp
20844     # . save registers
20845     51/push-ecx
20846     # var curr/ecx: (addr list var) = lookup(fn->outputs)
20847     8b/-> *(ebp+8) 0/r32/eax
20848     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
20849     89/<- %ecx 0/r32/eax
20850     # while curr != null
20851     {
20852       81 7/subop/compare %ecx 0/imm32
20853       74/jump-if-= break/disp8
20854       # var v/eax: (addr var) = lookup(curr->value)
20855       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20856       # var reg/eax: (addr array byte) = lookup(v->register)
20857       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20858       # if (reg == target) return true
20859       (string-equal? %eax *(ebp+0xc))  # => eax
20860       3d/compare-eax-and 0/imm32/false
20861       75/jump-if-!= $reg-in-function-outputs?:end/disp8
20862       # curr = curr->next
20863       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20864       89/<- %ecx 0/r32/eax
20865       #
20866       eb/jump loop/disp8
20867     }
20868     # return false
20869     b8/copy-to-eax 0/imm32
20870 $reg-in-function-outputs?:end:
20871     # . restore registers
20872     59/pop-to-ecx
20873     # . epilogue
20874     89/<- %esp 5/r32/ebp
20875     5d/pop-to-ebp
20876     c3/return
20877 
20878 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
20879     # . prologue
20880     55/push-ebp
20881     89/<- %ebp 4/r32/esp
20882     # . save registers
20883     50/push-eax
20884     51/push-ecx
20885     52/push-edx
20886     # eax = stmt
20887     8b/-> *(ebp+0xc) 0/r32/eax
20888     # var v/ecx: (addr var)
20889     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
20890     89/<- %ecx 0/r32/eax
20891     # v->block-depth = *Curr-block-depth
20892     8b/-> *Curr-block-depth 0/r32/eax
20893     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
20894     # var n/edx: int = size-of(stmt->var)
20895     (size-of %ecx)  # => eax
20896     89/<- %edx 0/r32/eax
20897     # *Curr-local-stack-offset -= n
20898     29/subtract-from *Curr-local-stack-offset 2/r32/edx
20899     # v->offset = *Curr-local-stack-offset
20900     8b/-> *Curr-local-stack-offset 0/r32/eax
20901     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
20902     # if v is an array, do something special to initialize it
20903     {
20904       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20905       (is-mu-array? %eax)  # => eax
20906       3d/compare-eax-and 0/imm32/false
20907       0f 84/jump-if-= break/disp32
20908       # var array-size-without-size/edx: int = n-4
20909       81 5/subop/subtract %edx 4/imm32
20910       #
20911       (emit-array-data-initialization *(ebp+8) %edx)
20912       e9/jump $emit-subx-var-def:end/disp32
20913     }
20914     # another special-case for initializing streams
20915     # a stream is an array with 2 extra pointers
20916     {
20917       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20918       (is-mu-stream? %eax)  # => eax
20919       3d/compare-eax-and 0/imm32/false
20920       0f 84/jump-if-= break/disp32
20921       # var array-size-without-size/edx: int = n-12
20922       81 5/subop/subtract %edx 0xc/imm32
20923       (emit-array-data-initialization *(ebp+8) %edx)
20924       # emit read and write pointers
20925       (emit-indent *(ebp+8) *Curr-block-depth)
20926       (write-buffered *(ebp+8) "68/push 0/imm32\n")
20927       (emit-indent *(ebp+8) *Curr-block-depth)
20928       (write-buffered *(ebp+8) "68/push 0/imm32\n")
20929       #
20930       eb/jump $emit-subx-var-def:end/disp8
20931     }
20932     # while n > 0
20933     {
20934       81 7/subop/compare %edx 0/imm32
20935       7e/jump-if-<= break/disp8
20936       (emit-indent *(ebp+8) *Curr-block-depth)
20937       (write-buffered *(ebp+8) "68/push 0/imm32\n")
20938       # n -= 4
20939       81 5/subop/subtract %edx 4/imm32
20940       #
20941       eb/jump loop/disp8
20942     }
20943 $emit-subx-var-def:end:
20944     # . restore registers
20945     5a/pop-to-edx
20946     59/pop-to-ecx
20947     58/pop-to-eax
20948     # . epilogue
20949     89/<- %esp 5/r32/ebp
20950     5d/pop-to-ebp
20951     c3/return
20952 
20953 emit-array-data-initialization:  # out: (addr buffered-file), n: int
20954     # . prologue
20955     55/push-ebp
20956     89/<- %ebp 4/r32/esp
20957     #
20958     (emit-indent *(ebp+8) *Curr-block-depth)
20959     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
20960     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
20961     (write-buffered *(ebp+8) ")\n")
20962     (emit-indent *(ebp+8) *Curr-block-depth)
20963     (write-buffered *(ebp+8) "68/push ")
20964     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
20965     (write-buffered *(ebp+8) "/imm32\n")
20966 $emit-array-data-initialization:end:
20967     # . epilogue
20968     89/<- %esp 5/r32/ebp
20969     5d/pop-to-ebp
20970     c3/return
20971 
20972 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
20973     # . prologue
20974     55/push-ebp
20975     89/<- %ebp 4/r32/esp
20976     # . save registers
20977     50/push-eax
20978     51/push-ecx
20979     # - some special-case primitives that don't actually use the 'primitives' data structure
20980     # var op/ecx: (addr array byte) = lookup(stmt->operation)
20981     8b/-> *(ebp+0xc) 1/r32/ecx
20982     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
20983     89/<- %ecx 0/r32/eax
20984     # array size
20985     {
20986       # if (!string-equal?(stmt->operation, "length")) break
20987       (string-equal? %ecx "length")  # => eax
20988       3d/compare-eax-and 0/imm32
20989       0f 84/jump-if-= break/disp32
20990       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20991       e9/jump $emit-subx-stmt:end/disp32
20992     }
20993     # index into array
20994     {
20995       # if (!string-equal?(stmt->operation, "index")) break
20996       (string-equal? %ecx "index")  # => eax
20997       3d/compare-eax-and 0/imm32
20998       0f 84/jump-if-= break/disp32
20999       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21000       e9/jump $emit-subx-stmt:end/disp32
21001     }
21002     # compute-offset for index into array
21003     {
21004       # if (!string-equal?(stmt->operation, "compute-offset")) break
21005       (string-equal? %ecx "compute-offset")  # => eax
21006       3d/compare-eax-and 0/imm32
21007       0f 84/jump-if-= break/disp32
21008       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21009       e9/jump $emit-subx-stmt:end/disp32
21010     }
21011     # get field from record
21012     {
21013       # if (!string-equal?(stmt->operation, "get")) break
21014       (string-equal? %ecx "get")  # => eax
21015       3d/compare-eax-and 0/imm32
21016       0f 84/jump-if-= break/disp32
21017       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
21018       e9/jump $emit-subx-stmt:end/disp32
21019     }
21020     # allocate scalar
21021     {
21022       # if (!string-equal?(stmt->operation, "allocate")) break
21023       (string-equal? %ecx "allocate")  # => eax
21024       3d/compare-eax-and 0/imm32
21025       0f 84/jump-if-= break/disp32
21026       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21027       e9/jump $emit-subx-stmt:end/disp32
21028     }
21029     # copy-object
21030     {
21031       # if (!string-equal?(stmt->operation, "copy-object")) break
21032       (string-equal? %ecx "copy-object")  # => eax
21033       3d/compare-eax-and 0/imm32
21034       0f 84/jump-if-= break/disp32
21035       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21036       e9/jump $emit-subx-stmt:end/disp32
21037     }
21038     # allocate array
21039     {
21040       # if (!string-equal?(stmt->operation, "populate")) break
21041       (string-equal? %ecx "populate")  # => eax
21042       3d/compare-eax-and 0/imm32
21043       0f 84/jump-if-= break/disp32
21044       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21045       e9/jump $emit-subx-stmt:end/disp32
21046     }
21047     # allocate stream
21048     {
21049       # if (!string-equal?(stmt->operation, "populate-stream")) break
21050       (string-equal? %ecx "populate-stream")  # => eax
21051       3d/compare-eax-and 0/imm32
21052       0f 84/jump-if-= break/disp32
21053       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21054       e9/jump $emit-subx-stmt:end/disp32
21055     }
21056     # read from stream
21057     {
21058       # if (!string-equal?(stmt->operation, "read-from-stream")) break
21059       (string-equal? %ecx "read-from-stream")  # => eax
21060       3d/compare-eax-and 0/imm32
21061       0f 84/jump-if-= break/disp32
21062       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21063       e9/jump $emit-subx-stmt:end/disp32
21064     }
21065     # write to stream
21066     {
21067       # if (!string-equal?(stmt->operation, "write-to-stream")) break
21068       (string-equal? %ecx "write-to-stream")  # => eax
21069       3d/compare-eax-and 0/imm32
21070       0f 84/jump-if-= break/disp32
21071       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
21072       e9/jump $emit-subx-stmt:end/disp32
21073     }
21074     # - if stmt matches a primitive, emit it
21075     {
21076 $emit-subx-stmt:check-for-primitive:
21077       # var curr/eax: (addr primitive)
21078       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
21079       3d/compare-eax-and 0/imm32
21080       74/jump-if-= break/disp8
21081 $emit-subx-stmt:primitive:
21082       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
21083       e9/jump $emit-subx-stmt:end/disp32
21084     }
21085     # - otherwise emit a call
21086     # TODO: type-checking
21087 $emit-subx-stmt:call:
21088     (emit-call *(ebp+8) *(ebp+0xc))
21089 $emit-subx-stmt:end:
21090     # . restore registers
21091     59/pop-to-ecx
21092     58/pop-to-eax
21093     # . epilogue
21094     89/<- %esp 5/r32/ebp
21095     5d/pop-to-ebp
21096     c3/return
21097 
21098 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21099     # . prologue
21100     55/push-ebp
21101     89/<- %ebp 4/r32/esp
21102     # . save registers
21103     50/push-eax
21104     51/push-ecx
21105     52/push-edx
21106     53/push-ebx
21107     56/push-esi
21108     # esi = stmt
21109     8b/-> *(ebp+0xc) 6/r32/esi
21110     # var base/ebx: (addr var) = stmt->inouts[0]->value
21111     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21112     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21113     89/<- %ebx 0/r32/eax
21114     # var elemsize/ecx: int = array-element-size(base)
21115     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
21116     89/<- %ecx 0/r32/eax
21117     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
21118     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21119     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21120     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21121     89/<- %edx 0/r32/eax
21122     # if elemsize == 1
21123     {
21124       81 7/subop/compare %ecx 1/imm32
21125       75/jump-if-!= break/disp8
21126 $translate-mu-length-stmt:size-1:
21127       (emit-save-size-to *(ebp+8) %ebx %edx)
21128       e9/jump $translate-mu-length-stmt:end/disp32
21129     }
21130     # if elemsize is a power of 2 less than 256
21131     {
21132       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
21133       3d/compare-eax-and 0/imm32/false
21134       74/jump-if-= break/disp8
21135       81 7/subop/compare %ecx 0xff/imm32
21136       7f/jump-if-> break/disp8
21137 $translate-mu-length-stmt:size-power-of-2:
21138       (emit-save-size-to *(ebp+8) %ebx %edx)
21139       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
21140       e9/jump $translate-mu-length-stmt:end/disp32
21141     }
21142     # otherwise, the complex case
21143     # . emit register spills
21144     {
21145 $translate-mu-length-stmt:complex:
21146       (string-equal? %edx "eax")  # => eax
21147       3d/compare-eax-and 0/imm32/false
21148       75/break-if-!= break/disp8
21149       (emit-indent *(ebp+8) *Curr-block-depth)
21150       (write-buffered *(ebp+8) "50/push-eax\n")
21151     }
21152     {
21153       (string-equal? %edx "ecx")  # => eax
21154       3d/compare-eax-and 0/imm32/false
21155       75/break-if-!= break/disp8
21156       (emit-indent *(ebp+8) *Curr-block-depth)
21157       (write-buffered *(ebp+8) "51/push-ecx\n")
21158     }
21159     {
21160       (string-equal? %edx "edx")  # => eax
21161       3d/compare-eax-and 0/imm32/false
21162       75/break-if-!= break/disp8
21163       (emit-indent *(ebp+8) *Curr-block-depth)
21164       (write-buffered *(ebp+8) "52/push-edx\n")
21165     }
21166     # .
21167     (emit-save-size-to *(ebp+8) %ebx "eax")
21168     (emit-indent *(ebp+8) *Curr-block-depth)
21169     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
21170     (emit-indent *(ebp+8) *Curr-block-depth)
21171     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
21172     (write-int32-hex-buffered *(ebp+8) %ecx)
21173     (write-buffered *(ebp+8) "/imm32\n")
21174     (emit-indent *(ebp+8) *Curr-block-depth)
21175     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
21176     {
21177       (string-equal? %edx "eax")  # => eax
21178       3d/compare-eax-and 0/imm32/false
21179       75/break-if-!= break/disp8
21180       (emit-indent *(ebp+8) *Curr-block-depth)
21181       (write-buffered *(ebp+8) "89/<- %")
21182       (write-buffered *(ebp+8) %edx)
21183       (write-buffered *(ebp+8) " 0/r32/eax\n")
21184     }
21185     # . emit register restores
21186     {
21187       (string-equal? %edx "edx")  # => eax
21188       3d/compare-eax-and 0/imm32/false
21189       75/break-if-!= break/disp8
21190       (emit-indent *(ebp+8) *Curr-block-depth)
21191       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
21192     }
21193     {
21194       (string-equal? %edx "ecx")  # => eax
21195       3d/compare-eax-and 0/imm32/false
21196       75/break-if-!= break/disp8
21197       (emit-indent *(ebp+8) *Curr-block-depth)
21198       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
21199     }
21200     {
21201       (string-equal? %edx "eax")  # => eax
21202       3d/compare-eax-and 0/imm32/false
21203       75/break-if-!= break/disp8
21204       (emit-indent *(ebp+8) *Curr-block-depth)
21205       (write-buffered *(ebp+8) "58/pop-to-eax\n")
21206     }
21207 $translate-mu-length-stmt:end:
21208     # . restore registers
21209     5e/pop-to-esi
21210     5b/pop-to-ebx
21211     5a/pop-to-edx
21212     59/pop-to-ecx
21213     58/pop-to-eax
21214     # . epilogue
21215     89/<- %esp 5/r32/ebp
21216     5d/pop-to-ebp
21217     c3/return
21218 
21219 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
21220     # . prologue
21221     55/push-ebp
21222     89/<- %ebp 4/r32/esp
21223     #
21224     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
21225     (size-of-type-id-as-array-element %eax)  # => eax
21226 $array-element-size:end:
21227     # . epilogue
21228     89/<- %esp 5/r32/ebp
21229     5d/pop-to-ebp
21230     c3/return
21231 
21232 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
21233     # precondition: n is positive
21234     # . prologue
21235     55/push-ebp
21236     89/<- %ebp 4/r32/esp
21237     #
21238     8b/-> *(ebp+8) 0/r32/eax
21239     # var t/eax: (addr type-tree)
21240     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21241     # if t == 0 abort
21242     3d/compare-eax-with 0/imm32
21243     0f 84/jump-if-== $array-element-type-id:error0/disp32
21244     # if t->is-atom? abort
21245     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21246     0f 85/jump-if-!= $array-element-type-id:error1/disp32
21247     # if (t->left == addr) t = t->right
21248     {
21249       50/push-eax
21250       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21251       (is-simple-mu-type? %eax 2)  # addr => eax
21252       3d/compare-eax-with 0/imm32/false
21253       58/pop-to-eax
21254       74/jump-if-= break/disp8
21255 $array-element-type-id:skip-addr:
21256       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21257     }
21258     # if t == 0 abort
21259     3d/compare-eax-with 0/imm32
21260     0f 84/jump-if-= $array-element-type-id:error2/disp32
21261     # if t->is-atom? abort
21262     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21263     0f 85/jump-if-!= $array-element-type-id:error2/disp32
21264     # if t->left != array abort
21265     {
21266       50/push-eax
21267       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21268       (is-simple-mu-type? %eax 3)  # array => eax
21269       3d/compare-eax-with 0/imm32/false
21270       58/pop-to-eax
21271 $array-element-type-id:no-array:
21272       0f 84/jump-if-= $array-element-type-id:error2/disp32
21273     }
21274 $array-element-type-id:skip-array:
21275     # t = t->right
21276     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21277     # if t == 0 abort
21278     3d/compare-eax-with 0/imm32
21279     0f 84/jump-if-= $array-element-type-id:error2/disp32
21280     # if t->is-atom? abort
21281     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21282     0f 85/jump-if-!= $array-element-type-id:error2/disp32
21283     # t = t->left
21284     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21285     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
21286     # if (t->is-atom == false) t = lookup(t->left)
21287     {
21288       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21289       75/jump-if-!= break/disp8
21290       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21291     }
21292     # return t->value
21293     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
21294 $array-element-type-id:end:
21295     # . epilogue
21296     89/<- %esp 5/r32/ebp
21297     5d/pop-to-ebp
21298     c3/return
21299 
21300 $array-element-type-id:error0:
21301     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
21302     50/push-eax
21303     8b/-> *(ebp+8) 0/r32/eax
21304     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21305     (write-buffered *(ebp+0xc) %eax)
21306     58/pop-to-eax
21307     (write-buffered *(ebp+0xc) "' has no type\n")
21308     (flush *(ebp+0xc))
21309     (stop *(ebp+0x10) 1)
21310     # never gets here
21311 
21312 $array-element-type-id:error1:
21313     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
21314     50/push-eax
21315     8b/-> *(ebp+8) 0/r32/eax
21316     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21317     (write-buffered *(ebp+0xc) %eax)
21318     58/pop-to-eax
21319     (write-buffered *(ebp+0xc) "' has atomic type ")
21320     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
21321     (write-buffered *(ebp+0xc) Newline)
21322     (flush *(ebp+0xc))
21323     (stop *(ebp+0x10) 1)
21324     # never gets here
21325 
21326 $array-element-type-id:error2:
21327     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
21328     50/push-eax
21329     8b/-> *(ebp+8) 0/r32/eax
21330     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21331     (write-buffered *(ebp+0xc) %eax)
21332     58/pop-to-eax
21333     (write-buffered *(ebp+0xc) "' has non-array type\n")
21334     (flush *(ebp+0xc))
21335     (stop *(ebp+0x10) 1)
21336     # never gets here
21337 
21338 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
21339     # . prologue
21340     55/push-ebp
21341     89/<- %ebp 4/r32/esp
21342     # eax = t
21343     8b/-> *(ebp+8) 0/r32/eax
21344     # if t is 'byte', size is 1
21345     3d/compare-eax-and 8/imm32/byte
21346     {
21347       75/jump-if-!= break/disp8
21348       b8/copy-to-eax 1/imm32
21349       eb/jump $size-of-type-id-as-array-element:end/disp8
21350     }
21351     # otherwise proceed as usual
21352     (size-of-type-id %eax)  # => eax
21353 $size-of-type-id-as-array-element:end:
21354     # . epilogue
21355     89/<- %esp 5/r32/ebp
21356     5d/pop-to-ebp
21357     c3/return
21358 
21359 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
21360     # . prologue
21361     55/push-ebp
21362     89/<- %ebp 4/r32/esp
21363     # . save registers
21364     50/push-eax
21365     53/push-ebx
21366     # ebx = base
21367     8b/-> *(ebp+0xc) 3/r32/ebx
21368     (emit-indent *(ebp+8) *Curr-block-depth)
21369     (write-buffered *(ebp+8) "8b/-> *")
21370     # if base is an (addr array ...) in a register
21371     {
21372       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
21373       74/jump-if-= break/disp8
21374 $emit-save-size-to:emit-base-from-register:
21375       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
21376       (write-buffered *(ebp+8) %eax)
21377       eb/jump $emit-save-size-to:emit-output/disp8
21378     }
21379     # otherwise if base is an (array ...) on the stack
21380     {
21381       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
21382       74/jump-if-= break/disp8
21383 $emit-save-size-to:emit-base-from-stack:
21384       (write-buffered *(ebp+8) "(ebp+")
21385       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
21386       (write-buffered *(ebp+8) ")")
21387     }
21388 $emit-save-size-to:emit-output:
21389     (write-buffered *(ebp+8) " ")
21390     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
21391     (write-int32-hex-buffered *(ebp+8) *eax)
21392     (write-buffered *(ebp+8) "/r32\n")
21393 $emit-save-size-to:end:
21394     # . restore registers
21395     5b/pop-to-ebx
21396     58/pop-to-eax
21397     # . epilogue
21398     89/<- %esp 5/r32/ebp
21399     5d/pop-to-ebp
21400     c3/return
21401 
21402 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
21403     # . prologue
21404     55/push-ebp
21405     89/<- %ebp 4/r32/esp
21406     # . save registers
21407     50/push-eax
21408     #
21409     (emit-indent *(ebp+8) *Curr-block-depth)
21410     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
21411     (write-buffered *(ebp+8) *(ebp+0xc))
21412     (write-buffered *(ebp+8) Space)
21413     (num-shift-rights *(ebp+0x10))  # => eax
21414     (write-int32-hex-buffered *(ebp+8) %eax)
21415     (write-buffered *(ebp+8) "/imm8\n")
21416 $emit-divide-by-shift-right:end:
21417     # . restore registers
21418     58/pop-to-eax
21419     # . epilogue
21420     89/<- %esp 5/r32/ebp
21421     5d/pop-to-ebp
21422     c3/return
21423 
21424 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21425     # . prologue
21426     55/push-ebp
21427     89/<- %ebp 4/r32/esp
21428     # . save registers
21429     51/push-ecx
21430     # ecx = stmt
21431     8b/-> *(ebp+0xc) 1/r32/ecx
21432     # var base/ecx: (addr var) = stmt->inouts[0]
21433     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21434     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21435     89/<- %ecx 0/r32/eax
21436     # if (var->register) do one thing
21437     {
21438       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21439       74/jump-if-= break/disp8
21440       # TODO: ensure there's no dereference
21441       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21442       eb/jump $translate-mu-index-stmt:end/disp8
21443     }
21444     # if (var->offset) do a different thing
21445     {
21446       81 7/subop/compare *(ecx+0x14) 0/imm32  # Var-offset
21447       74/jump-if-= break/disp8
21448       # TODO: ensure there's no dereference
21449       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21450       eb/jump $translate-mu-index-stmt:end/disp8
21451     }
21452 $translate-mu-index-stmt:end:
21453     # . restore registers
21454     59/pop-to-ecx
21455     # . epilogue
21456     89/<- %esp 5/r32/ebp
21457     5d/pop-to-ebp
21458     c3/return
21459 
21460 $translate-mu-index-stmt-with-array:error1:
21461     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
21462     (flush *(ebp+0x10))
21463     (stop *(ebp+0x14) 1)
21464     # never gets here
21465 
21466 $translate-mu-index-stmt-with-array:error2:
21467     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
21468     (flush *(ebp+0x10))
21469     (stop *(ebp+0x14) 1)
21470     # never gets here
21471 
21472 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21473     # . prologue
21474     55/push-ebp
21475     89/<- %ebp 4/r32/esp
21476     # . save registers
21477     50/push-eax
21478     51/push-ecx
21479     52/push-edx
21480     53/push-ebx
21481     #
21482     (emit-indent *(ebp+8) *Curr-block-depth)
21483     (write-buffered *(ebp+8) "8d/copy-address *(")
21484     # TODO: ensure inouts[0] is in a register and not dereferenced
21485 $translate-mu-index-stmt-with-array-in-register:emit-base:
21486     # ecx = stmt
21487     8b/-> *(ebp+0xc) 1/r32/ecx
21488     # var base/ebx: (addr var) = inouts[0]
21489     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21490     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21491     89/<- %ebx 0/r32/eax
21492     # print base->register " + "
21493     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
21494     (write-buffered *(ebp+8) %eax)
21495     (write-buffered *(ebp+8) " + ")
21496     # var index/edx: (addr var) = inouts[1]
21497     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21498     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21499     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21500     89/<- %edx 0/r32/eax
21501     # if index->register
21502     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
21503     {
21504       0f 84/jump-if-= break/disp32
21505 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
21506       # if index is an int
21507       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
21508       (is-simple-mu-type? %eax 1)  # int => eax
21509       3d/compare-eax-and 0/imm32/false
21510       {
21511         0f 84/jump-if-= break/disp32
21512 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
21513         # print index->register "<<" log2(array-element-size(base)) " + 4) "
21514         # . index->register "<<"
21515         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
21516         (write-buffered *(ebp+8) %eax)
21517         (write-buffered *(ebp+8) "<<")
21518         # . log2(array-element-size(base->type))
21519         # TODO: ensure size is a power of 2
21520         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
21521         (num-shift-rights %eax)  # => eax
21522         (write-int32-hex-buffered *(ebp+8) %eax)
21523         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
21524       }
21525       # if index->type is any other atom, abort
21526       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
21527       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21528       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
21529       # if index has type (offset ...)
21530       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21531       (is-simple-mu-type? %eax 7)  # => eax
21532       3d/compare-eax-and 0/imm32/false
21533       {
21534         0f 84/jump-if-= break/disp32
21535         # print index->register
21536 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
21537         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
21538         (write-buffered *(ebp+8) %eax)
21539       }
21540 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
21541       (write-buffered *(ebp+8) " + 4) ")
21542       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
21543     }
21544     # otherwise if index is a literal
21545     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
21546     (is-simple-mu-type? %eax 0)  # => eax
21547     3d/compare-eax-and 0/imm32/false
21548     {
21549       0f 84/jump-if-= break/disp32
21550 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
21551       # var index-value/edx: int = parse-hex-int(index->name)
21552       (lookup *edx *(edx+4))  # Var-name Var-name => eax
21553       (parse-hex-int %eax)  # => eax
21554       89/<- %edx 0/r32/eax
21555       # offset = idx-value * array-element-size(base->type)
21556       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
21557       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
21558       # offset += 4 for array size
21559       05/add-to-eax 4/imm32
21560       # TODO: check edx for overflow
21561       # print offset
21562       (write-int32-hex-buffered *(ebp+8) %eax)
21563       (write-buffered *(ebp+8) ") ")
21564       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
21565     }
21566     # otherwise abort
21567     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
21568 $translate-mu-index-stmt-with-array-in-register:emit-output:
21569     # outputs[0] "/r32"
21570     8b/-> *(ebp+0xc) 1/r32/ecx
21571     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21572     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21573     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21574     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
21575     (write-int32-hex-buffered *(ebp+8) *eax)
21576     (write-buffered *(ebp+8) "/r32\n")
21577 $translate-mu-index-stmt-with-array-in-register:end:
21578     # . restore registers
21579     5b/pop-to-ebx
21580     5a/pop-to-edx
21581     59/pop-to-ecx
21582     58/pop-to-eax
21583     # . epilogue
21584     89/<- %esp 5/r32/ebp
21585     5d/pop-to-ebp
21586     c3/return
21587 
21588 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21589     # . prologue
21590     55/push-ebp
21591     89/<- %ebp 4/r32/esp
21592     # . save registers
21593     50/push-eax
21594     51/push-ecx
21595     52/push-edx
21596     53/push-ebx
21597     #
21598     (emit-indent *(ebp+8) *Curr-block-depth)
21599     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
21600     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
21601     8b/-> *(ebp+0xc) 0/r32/eax
21602     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21603     89/<- %edx 0/r32/eax
21604     # var base/ecx: (addr var) = lookup(curr->value)
21605     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21606     89/<- %ecx 0/r32/eax
21607     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
21608     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
21609     # var index/edx: (handle var) = curr2->value
21610     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21611     89/<- %edx 0/r32/eax
21612     # if index->register
21613     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
21614     {
21615       0f 84/jump-if-= break/disp32
21616 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
21617       # if index is an int
21618       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
21619       (is-simple-mu-type? %eax 1)  # int => eax
21620       3d/compare-eax-and 0/imm32/false
21621       {
21622         0f 84/jump-if-= break/disp32
21623 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
21624         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
21625         # . inouts[1]->register "<<"
21626         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
21627         (write-buffered *(ebp+8) %eax)
21628         (write-buffered *(ebp+8) "<<")
21629         # . log2(array-element-size(base))
21630         # TODO: ensure size is a power of 2
21631         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
21632         (num-shift-rights %eax)  # => eax
21633         (write-int32-hex-buffered *(ebp+8) %eax)
21634         #
21635         (write-buffered *(ebp+8) " + ")
21636         #
21637         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
21638         05/add-to-eax 4/imm32  # for array length
21639         (write-int32-hex-buffered *(ebp+8) %eax)
21640         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
21641       }
21642       # if index->type is any other atom, abort
21643       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
21644       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21645       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
21646       # if index has type (offset ...)
21647       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21648       (is-simple-mu-type? %eax 7)  # => eax
21649       3d/compare-eax-and 0/imm32/false
21650       {
21651         0f 84/jump-if-= break/disp32
21652         # print index->register
21653 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
21654         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
21655         (write-buffered *(ebp+8) %eax)
21656       }
21657 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
21658       (write-buffered *(ebp+8) ") ")
21659       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
21660     }
21661     # otherwise if index is a literal
21662     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
21663     (is-simple-mu-type? %eax 0)  # => eax
21664     3d/compare-eax-and 0/imm32/false
21665     {
21666       0f 84/jump-if-= break/disp32
21667 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
21668       # var idx-value/edx: int = parse-hex-int(index->name)
21669       (lookup *edx *(edx+4))  # Var-name Var-name => eax
21670       (parse-hex-int %eax)  # Var-name => eax
21671       89/<- %edx 0/r32/eax
21672       # offset = idx-value * array-element-size(base)
21673       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
21674       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
21675       # offset += base->offset
21676       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
21677       # offset += 4 for array size
21678       05/add-to-eax 4/imm32
21679       # TODO: check edx for overflow
21680       # print offset
21681       (write-int32-hex-buffered *(ebp+8) %eax)
21682       (write-buffered *(ebp+8) ") ")
21683       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
21684     }
21685     # otherwise abort
21686     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
21687 $translate-mu-index-stmt-with-array-on-stack:emit-output:
21688     # outputs[0] "/r32"
21689     8b/-> *(ebp+0xc) 0/r32/eax
21690     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21691     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21692     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21693     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
21694     (write-int32-hex-buffered *(ebp+8) *eax)
21695     (write-buffered *(ebp+8) "/r32\n")
21696 $translate-mu-index-stmt-with-array-on-stack:end:
21697     # . restore registers
21698     5b/pop-to-ebx
21699     5a/pop-to-edx
21700     59/pop-to-ecx
21701     58/pop-to-eax
21702     # . epilogue
21703     89/<- %esp 5/r32/ebp
21704     5d/pop-to-ebp
21705     c3/return
21706 
21707 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21708     # . prologue
21709     55/push-ebp
21710     89/<- %ebp 4/r32/esp
21711     # . save registers
21712     50/push-eax
21713     51/push-ecx
21714     52/push-edx
21715     53/push-ebx
21716     #
21717     (emit-indent *(ebp+8) *Curr-block-depth)
21718     (write-buffered *(ebp+8) "69/multiply")
21719     # ecx = stmt
21720     8b/-> *(ebp+0xc) 1/r32/ecx
21721     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
21722     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21723     89/<- %ebx 0/r32/eax
21724 $translate-mu-compute-index-stmt:emit-index:
21725     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
21726     (emit-subx-var-as-rm32 *(ebp+8) %eax)
21727     (write-buffered *(ebp+8) Space)
21728 $translate-mu-compute-index-stmt:emit-elem-size:
21729     # var base/ebx: (addr var)
21730     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
21731     89/<- %ebx 0/r32/eax
21732     # print array-element-size(base)
21733     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
21734     (write-int32-hex-buffered *(ebp+8) %eax)
21735     (write-buffered *(ebp+8) "/imm32 ")
21736 $translate-mu-compute-index-stmt:emit-output:
21737     # outputs[0] "/r32"
21738     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21739     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21740     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21741     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
21742     (write-int32-hex-buffered *(ebp+8) *eax)
21743     (write-buffered *(ebp+8) "/r32\n")
21744 $translate-mu-compute-index-stmt:end:
21745     # . restore registers
21746     5b/pop-to-ebx
21747     5a/pop-to-edx
21748     59/pop-to-ecx
21749     58/pop-to-eax
21750     # . epilogue
21751     89/<- %esp 5/r32/ebp
21752     5d/pop-to-ebp
21753     c3/return
21754 
21755 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
21756     # . prologue
21757     55/push-ebp
21758     89/<- %ebp 4/r32/esp
21759     # . save registers
21760     50/push-eax
21761     51/push-ecx
21762     52/push-edx
21763     #
21764     (emit-indent *(ebp+8) *Curr-block-depth)
21765     (write-buffered *(ebp+8) "8d/copy-address ")
21766     # ecx = stmt
21767     8b/-> *(ebp+0xc) 1/r32/ecx
21768     # var offset/edx: int = get offset of stmt
21769     (mu-get-offset %ecx)  # => eax
21770     89/<- %edx 0/r32/eax
21771     # var base/eax: (addr var) = stmt->inouts->value
21772     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21773     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21774     # if base is in a register
21775     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
21776     {
21777       0f 84/jump-if-= break/disp32
21778 $translate-mu-get-stmt:emit-register-input:
21779       # emit "*(" base->register " + " offset ") "
21780       (write-buffered *(ebp+8) "*(")
21781       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21782       (write-buffered *(ebp+8) %eax)
21783       (write-buffered *(ebp+8) " + ")
21784       (write-int32-hex-buffered *(ebp+8) %edx)
21785       (write-buffered *(ebp+8) ") ")
21786       e9/jump $translate-mu-get-stmt:emit-output/disp32
21787     }
21788     # otherwise base is on the stack
21789     {
21790 $translate-mu-get-stmt:emit-stack-input:
21791       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
21792       (write-buffered *(ebp+8) "*(ebp+")
21793       03/add *(eax+0x14) 2/r32/edx  # Var-offset
21794       (write-int32-hex-buffered *(ebp+8) %edx)
21795       (write-buffered *(ebp+8) ") ")
21796       eb/jump $translate-mu-get-stmt:emit-output/disp8
21797     }
21798 $translate-mu-get-stmt:emit-output:
21799     # var output/eax: (addr var) = stmt->outputs->value
21800     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21801     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21802     # emit offset->register "/r32"
21803     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21804     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
21805     (write-int32-hex-buffered *(ebp+8) *eax)
21806     (write-buffered *(ebp+8) "/r32\n")
21807 $translate-mu-get-stmt:end:
21808     # . restore registers
21809     5a/pop-to-edx
21810     59/pop-to-ecx
21811     58/pop-to-eax
21812     # . epilogue
21813     89/<- %esp 5/r32/ebp
21814     5d/pop-to-ebp
21815     c3/return
21816 
21817 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21818     # . prologue
21819     55/push-ebp
21820     89/<- %ebp 4/r32/esp
21821     # . save registers
21822     50/push-eax
21823     #
21824     (emit-indent *(ebp+8) *Curr-block-depth)
21825     (write-buffered *(ebp+8) "(copy-bytes")
21826     # eax = stmt
21827     8b/-> *(ebp+0xc) 0/r32/eax
21828     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
21829     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21830     (emit-subx-call-operand *(ebp+8) %eax)
21831     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21832     (emit-subx-call-operand *(ebp+8) %eax)
21833     (write-buffered *(ebp+8) Space)
21834     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
21835     (write-int32-hex-buffered *(ebp+8) %eax)
21836     (write-buffered *(ebp+8) ")\n")
21837 $translate-mu-copy-object-stmt:end:
21838     # . restore registers
21839     58/pop-to-eax
21840     # . epilogue
21841     89/<- %esp 5/r32/ebp
21842     5d/pop-to-ebp
21843     c3/return
21844 
21845 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21846     # . prologue
21847     55/push-ebp
21848     89/<- %ebp 4/r32/esp
21849     # . save registers
21850     50/push-eax
21851     56/push-esi
21852     57/push-edi
21853     # esi = stmt
21854     8b/-> *(ebp+0xc) 6/r32/esi
21855     # var target/edi: (addr stmt-var) = stmt->inouts[0]
21856     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21857     89/<- %edi 0/r32/eax
21858     #
21859     (emit-indent *(ebp+8) *Curr-block-depth)
21860     (write-buffered *(ebp+8) "(allocate Heap ")
21861     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
21862     (write-int32-hex-buffered *(ebp+8) %eax)
21863     (emit-subx-call-operand *(ebp+8) %edi)
21864     (write-buffered *(ebp+8) ")\n")
21865 $translate-mu-allocate-stmt:end:
21866     # . restore registers
21867     5f/pop-to-edi
21868     5e/pop-to-esi
21869     58/pop-to-eax
21870     # . epilogue
21871     89/<- %esp 5/r32/ebp
21872     5d/pop-to-ebp
21873     c3/return
21874 
21875 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
21876     # . prologue
21877     55/push-ebp
21878     89/<- %ebp 4/r32/esp
21879     # var t/eax: (addr type-tree) = s->value->type
21880     8b/-> *(ebp+8) 0/r32/eax
21881     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21882     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21883     # TODO: check eax != 0
21884     # TODO: check !t->is-atom?
21885     # TODO: check t->left == addr
21886     # t = t->right
21887 $addr-handle-payload-size:skip-addr:
21888     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21889     # TODO: check eax != 0
21890     # TODO: check !t->is-atom?
21891     # TODO: check t->left == handle
21892     # t = t->right
21893 $addr-handle-payload-size:skip-handle:
21894     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21895     # TODO: check eax != 0
21896     # if !t->is-atom? t = t->left
21897     81 7/subop/compare *eax 0/imm32/false
21898     {
21899       75/jump-if-!= break/disp8
21900       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21901     }
21902     # TODO: check t->is-atom?
21903     # return size(t->value)
21904     (size-of-type-id *(eax+4))  # Type-tree-value => eax
21905 $addr-handle-payload-size:end:
21906     # . epilogue
21907     89/<- %esp 5/r32/ebp
21908     5d/pop-to-ebp
21909     c3/return
21910 
21911 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
21912     # . prologue
21913     55/push-ebp
21914     89/<- %ebp 4/r32/esp
21915     # var t/eax: (addr type-tree) = s->value->type
21916     8b/-> *(ebp+8) 0/r32/eax
21917     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21918     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21919     # TODO: check eax != 0
21920     # TODO: check !t->is-atom?
21921     # TODO: check t->left == addr
21922     # t = t->right
21923 $addr-payload-size:skip-addr:
21924     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21925     # TODO: check eax != 0
21926     # if !t->is-atom? t = t->left
21927     81 7/subop/compare *eax 0/imm32/false
21928     {
21929       75/jump-if-!= break/disp8
21930       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21931     }
21932     # TODO: check t->is-atom?
21933     # return size(t->value)
21934     (size-of-type-id *(eax+4))  # Type-tree-value => eax
21935 $addr-payload-size:end:
21936     # . epilogue
21937     89/<- %esp 5/r32/ebp
21938     5d/pop-to-ebp
21939     c3/return
21940 
21941 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21942     # . prologue
21943     55/push-ebp
21944     89/<- %ebp 4/r32/esp
21945     # . save registers
21946     50/push-eax
21947     51/push-ecx
21948     56/push-esi
21949     57/push-edi
21950     # esi = stmt
21951     8b/-> *(ebp+0xc) 6/r32/esi
21952     # var target/edi: (addr stmt-var) = stmt->inouts[0]
21953     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21954     89/<- %edi 0/r32/eax
21955     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
21956     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21957     89/<- %ecx 0/r32/eax
21958     #
21959     (emit-indent *(ebp+8) *Curr-block-depth)
21960     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
21961     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
21962     (write-int32-hex-buffered *(ebp+8) %eax)
21963     (emit-subx-call-operand *(ebp+8) %ecx)
21964     (emit-subx-call-operand *(ebp+8) %edi)
21965     (write-buffered *(ebp+8) ")\n")
21966 $translate-mu-populate-stmt:end:
21967     # . restore registers
21968     5f/pop-to-edi
21969     5e/pop-to-esi
21970     59/pop-to-ecx
21971     58/pop-to-eax
21972     # . epilogue
21973     89/<- %esp 5/r32/ebp
21974     5d/pop-to-ebp
21975     c3/return
21976 
21977 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21978     # . prologue
21979     55/push-ebp
21980     89/<- %ebp 4/r32/esp
21981     # . save registers
21982     50/push-eax
21983     51/push-ecx
21984     56/push-esi
21985     57/push-edi
21986     # esi = stmt
21987     8b/-> *(ebp+0xc) 6/r32/esi
21988     # var target/edi: (addr stmt-var) = stmt->inouts[0]
21989     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21990     89/<- %edi 0/r32/eax
21991     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
21992     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21993     89/<- %ecx 0/r32/eax
21994     #
21995     (emit-indent *(ebp+8) *Curr-block-depth)
21996     (write-buffered *(ebp+8) "(new-stream Heap ")
21997     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
21998     (write-int32-hex-buffered *(ebp+8) %eax)
21999     (emit-subx-call-operand *(ebp+8) %ecx)
22000     (emit-subx-call-operand *(ebp+8) %edi)
22001     (write-buffered *(ebp+8) ")\n")
22002 $translate-mu-populate-stream-stmt:end:
22003     # . restore registers
22004     5f/pop-to-edi
22005     5e/pop-to-esi
22006     59/pop-to-ecx
22007     58/pop-to-eax
22008     # . epilogue
22009     89/<- %esp 5/r32/ebp
22010     5d/pop-to-ebp
22011     c3/return
22012 
22013 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
22014     # . prologue
22015     55/push-ebp
22016     89/<- %ebp 4/r32/esp
22017     # . save registers
22018     50/push-eax
22019     51/push-ecx
22020     56/push-esi
22021     57/push-edi
22022     # esi = stmt
22023     8b/-> *(ebp+0xc) 6/r32/esi
22024     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
22025     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22026     89/<- %ecx 0/r32/eax
22027     # var target/edi: (addr stmt-var) = stmt->inouts[1]
22028     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
22029     89/<- %edi 0/r32/eax
22030     #
22031     (emit-indent *(ebp+8) *Curr-block-depth)
22032     (write-buffered *(ebp+8) "(read-from-stream")
22033     (emit-subx-call-operand *(ebp+8) %ecx)
22034     (emit-subx-call-operand *(ebp+8) %edi)
22035     (write-buffered *(ebp+8) Space)
22036     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
22037     (write-int32-hex-buffered *(ebp+8) %eax)
22038     (write-buffered *(ebp+8) ")\n")
22039 $translate-mu-read-from-stream-stmt:end:
22040     # . restore registers
22041     5f/pop-to-edi
22042     5e/pop-to-esi
22043     59/pop-to-ecx
22044     58/pop-to-eax
22045     # . epilogue
22046     89/<- %esp 5/r32/ebp
22047     5d/pop-to-ebp
22048     c3/return
22049 
22050 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
22051     # . prologue
22052     55/push-ebp
22053     89/<- %ebp 4/r32/esp
22054     # . save registers
22055     50/push-eax
22056     51/push-ecx
22057     56/push-esi
22058     57/push-edi
22059     # esi = stmt
22060     8b/-> *(ebp+0xc) 6/r32/esi
22061     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
22062     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22063     89/<- %ecx 0/r32/eax
22064     # var target/edi: (addr stmt-var) = stmt->inouts[1]
22065     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
22066     89/<- %edi 0/r32/eax
22067     #
22068     (emit-indent *(ebp+8) *Curr-block-depth)
22069     (write-buffered *(ebp+8) "(write-to-stream")
22070     (emit-subx-call-operand *(ebp+8) %ecx)
22071     (flush *(ebp+8))
22072     (emit-subx-call-operand *(ebp+8) %edi)
22073     (flush *(ebp+8))
22074     (write-buffered *(ebp+8) Space)
22075     (flush *(ebp+8))
22076     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
22077     (write-int32-hex-buffered *(ebp+8) %eax)
22078     (write-buffered *(ebp+8) ")\n")
22079 $translate-mu-write-to-stream-stmt:end:
22080     # . restore registers
22081     5f/pop-to-edi
22082     5e/pop-to-esi
22083     59/pop-to-ecx
22084     58/pop-to-eax
22085     # . epilogue
22086     89/<- %esp 5/r32/ebp
22087     5d/pop-to-ebp
22088     c3/return
22089 
22090 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
22091     # . prologue
22092     55/push-ebp
22093     89/<- %ebp 4/r32/esp
22094     # var t/eax: (addr type-tree) = s->value->type
22095     8b/-> *(ebp+8) 0/r32/eax
22096     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22097     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22098     # TODO: check eax != 0
22099     # TODO: check !t->is-atom?
22100     # TODO: check t->left == addr
22101     # t = t->right
22102 $addr-handle-array-payload-size:skip-addr:
22103     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22104     # TODO: check eax != 0
22105     # TODO: check !t->is-atom?
22106     # TODO: check t->left == handle
22107     # t = t->right
22108 $addr-handle-array-payload-size:skip-handle:
22109     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22110     # TODO: check eax != 0
22111     # TODO: check !t->is-atom?
22112     # TODO: check t->left == array
22113     # t = t->right
22114 $addr-handle-array-payload-size:skip-array:
22115     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22116     # TODO: check eax != 0
22117     # if !t->is-atom? t = t->left
22118     81 7/subop/compare *eax 0/imm32/false
22119     {
22120       75/jump-if-!= break/disp8
22121       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22122     }
22123 $addr-handle-array-payload-size:compute-size:
22124     # TODO: check t->is-atom?
22125     # return size(t->value)
22126     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
22127 $addr-handle-array-payload-size:end:
22128     # . epilogue
22129     89/<- %esp 5/r32/ebp
22130     5d/pop-to-ebp
22131     c3/return
22132 
22133 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
22134     # . prologue
22135     55/push-ebp
22136     89/<- %ebp 4/r32/esp
22137     # var t/eax: (addr type-tree) = s->value->type
22138     8b/-> *(ebp+8) 0/r32/eax
22139     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22140     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22141     # TODO: check eax != 0
22142     # TODO: check !t->is-atom?
22143     # TODO: check t->left == addr
22144     # t = t->right
22145 $addr-handle-stream-payload-size:skip-addr:
22146     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22147     # TODO: check eax != 0
22148     # TODO: check !t->is-atom?
22149     # TODO: check t->left == handle
22150     # t = t->right
22151 $addr-handle-stream-payload-size:skip-handle:
22152     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22153     # TODO: check eax != 0
22154     # TODO: check !t->is-atom?
22155     # TODO: check t->left == stream
22156     # t = t->right
22157 $addr-handle-stream-payload-size:skip-stream:
22158     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22159     # TODO: check eax != 0
22160     # if !t->is-atom? t = t->left
22161     81 7/subop/compare *eax 0/imm32/false
22162     {
22163       75/jump-if-!= break/disp8
22164       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22165     }
22166 $addr-handle-stream-payload-size:compute-size:
22167     # TODO: check t->is-atom?
22168     # return size(t->value)
22169     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
22170 $addr-handle-stream-payload-size:end:
22171     # . epilogue
22172     89/<- %esp 5/r32/ebp
22173     5d/pop-to-ebp
22174     c3/return
22175 
22176 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
22177     # precondition: n is positive
22178     # . prologue
22179     55/push-ebp
22180     89/<- %ebp 4/r32/esp
22181     # eax = n
22182     8b/-> *(ebp+8) 0/r32/eax
22183     # if (n < 0) abort
22184     3d/compare-eax-with 0/imm32
22185     0f 8c/jump-if-< $power-of-2?:abort/disp32
22186     # var tmp/eax: int = n-1
22187     48/decrement-eax
22188     # var tmp2/eax: int = n & tmp
22189     23/and-> *(ebp+8) 0/r32/eax
22190     # return (tmp2 == 0)
22191     3d/compare-eax-and 0/imm32
22192     0f 94/set-byte-if-= %al
22193     81 4/subop/and %eax 0xff/imm32
22194 $power-of-2?:end:
22195     # . epilogue
22196     89/<- %esp 5/r32/ebp
22197     5d/pop-to-ebp
22198     c3/return
22199 
22200 $power-of-2?:abort:
22201     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
22202     (flush *(ebp+0xc))
22203     (stop *(ebp+0x10) 1)
22204     # never gets here
22205 
22206 num-shift-rights:  # n: int -> result/eax: int
22207     # precondition: n is a positive power of 2
22208     # . prologue
22209     55/push-ebp
22210     89/<- %ebp 4/r32/esp
22211     # . save registers
22212     51/push-ecx
22213     # var curr/ecx: int = n
22214     8b/-> *(ebp+8) 1/r32/ecx
22215     # result = 0
22216     b8/copy-to-eax 0/imm32
22217     {
22218       # if (curr <= 1) break
22219       81 7/subop/compare %ecx 1/imm32
22220       7e/jump-if-<= break/disp8
22221       40/increment-eax
22222       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
22223       eb/jump loop/disp8
22224     }
22225 $num-shift-rights:end:
22226     # . restore registers
22227     59/pop-to-ecx
22228     # . epilogue
22229     89/<- %esp 5/r32/ebp
22230     5d/pop-to-ebp
22231     c3/return
22232 
22233 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
22234     # . prologue
22235     55/push-ebp
22236     89/<- %ebp 4/r32/esp
22237     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
22238     8b/-> *(ebp+8) 0/r32/eax
22239     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22240     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22241     # var output-var/eax: (addr var) = second-inout->value
22242     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22243 #?     (write-buffered Stderr "mu-get-offset: ")
22244 #?     (write-int32-hex-buffered Stderr %eax)
22245 #?     (write-buffered Stderr " name: ")
22246 #?     50/push-eax
22247 #?     (lookup *eax *(eax+4))  # Var-name
22248 #?     (write-buffered Stderr %eax)
22249 #?     58/pop-to-eax
22250 #?     (write-buffered Stderr Newline)
22251 #?     (flush Stderr)
22252     # return output-var->stack-offset
22253     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
22254 #?     (write-buffered Stderr "=> ")
22255 #?     (write-int32-hex-buffered Stderr %eax)
22256 #?     (write-buffered Stderr Newline)
22257 #?     (flush Stderr)
22258 $emit-get-offset:end:
22259     # . epilogue
22260     89/<- %esp 5/r32/ebp
22261     5d/pop-to-ebp
22262     c3/return
22263 
22264 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)
22265     # . prologue
22266     55/push-ebp
22267     89/<- %ebp 4/r32/esp
22268     # . save registers
22269     50/push-eax
22270     51/push-ecx
22271     56/push-esi
22272     # esi = block
22273     8b/-> *(ebp+0xc) 6/r32/esi
22274     # block->var->block-depth = *Curr-block-depth
22275     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
22276     8b/-> *Curr-block-depth 1/r32/ecx
22277     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
22278     # var stmts/eax: (addr list stmt) = lookup(block->statements)
22279     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
22280     #
22281     {
22282 $emit-subx-block:check-empty:
22283       3d/compare-eax-and 0/imm32
22284       0f 84/jump-if-= break/disp32
22285       (emit-indent *(ebp+8) *Curr-block-depth)
22286       (write-buffered *(ebp+8) "{\n")
22287       # var v/ecx: (addr var) = lookup(block->var)
22288       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
22289       89/<- %ecx 0/r32/eax
22290       #
22291       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22292       (write-buffered *(ebp+8) %eax)
22293       (write-buffered *(ebp+8) ":loop:\n")
22294       ff 0/subop/increment *Curr-block-depth
22295       (push *(ebp+0x10) *(esi+0xc))  # Block-var
22296       (push *(ebp+0x10) *(esi+0x10))  # Block-var
22297       (push *(ebp+0x10) 0)  # false
22298       # emit block->statements
22299       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
22300       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
22301       (pop *(ebp+0x10))  # => eax
22302       (pop *(ebp+0x10))  # => eax
22303       (pop *(ebp+0x10))  # => eax
22304       ff 1/subop/decrement *Curr-block-depth
22305       (emit-indent *(ebp+8) *Curr-block-depth)
22306       (write-buffered *(ebp+8) "}\n")
22307       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22308       (write-buffered *(ebp+8) %eax)
22309       (write-buffered *(ebp+8) ":break:\n")
22310     }
22311 $emit-subx-block:end:
22312     # . restore registers
22313     5e/pop-to-esi
22314     59/pop-to-ecx
22315     58/pop-to-eax
22316     # . epilogue
22317     89/<- %esp 5/r32/ebp
22318     5d/pop-to-ebp
22319     c3/return
22320 
22321 # Primitives supported
22322 # See mu_instructions for a summary of this linked-list data structure.
22323 #
22324 # For each operation, put variants with hard-coded registers before flexible ones.
22325 #
22326 # Unfortunately, our restrictions on addresses require that various fields in
22327 # primitives be handles, which complicates these definitions.
22328 #   - we need to insert dummy fields all over the place for fake alloc-ids
22329 #   - we can't use our syntax sugar of quoted literals for string fields
22330 #
22331 # Fake alloc-ids are needed because our type definitions up top require
22332 # handles but it's clearer to statically allocate these long-lived objects.
22333 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
22334 #
22335 # Every 'object' below starts with a fake alloc-id. It may also contain other
22336 # fake alloc-ids for various handle fields.
22337 #
22338 # I think of objects starting with a fake alloc-id as having type 'payload'.
22339 # It's not really intended to be created dynamically; for that use `allocate`
22340 # as usual.
22341 #
22342 # Idea for a notation to simplify such definitions:
22343 #   _Primitive-increment-eax:  # (payload primitive)
22344 #     0x11/alloc-id:fake:payload
22345 #     0x11 @(0x11 "increment")  # name
22346 #     0 0                       # inouts
22347 #     0x11 @(0x11/payload
22348 #            0x11 @(0x11/payload  # List-value
22349 #                   0 0             # Var-name
22350 #                   0x11 @(0x11     # Var-type
22351 #                          1/is-atom
22352 #                          1/value 0/unused   # Type-tree-left
22353 #                          0 0                # Type-tree-right
22354 #                         )
22355 #                   1               # block-depth
22356 #                   0               # stack-offset
22357 #                   0x11 @(0x11 "eax")  # Var-register
22358 #                  )
22359 #            0 0)                 # List-next
22360 #     ...
22361 #     _Primitive-increment-ecx/imm32/next
22362 #   ...
22363 # Awfully complex and non-obvious. But also clearly signals there's something
22364 # to learn here, so may be worth trying.
22365 #
22366 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
22367 #
22368 # For now we'll continue to just use comments and manually ensure they stay up
22369 # to date.
22370 == data
22371 Primitives:  # (addr primitive)
22372 # - increment/decrement
22373 _Primitive-increment-eax:  # (addr primitive)
22374     # var/eax <- increment => 40/increment-eax
22375     0x11/imm32/alloc-id:fake
22376     _string-increment/imm32/name
22377     0/imm32/no-inouts
22378     0/imm32/no-inouts
22379     0x11/imm32/alloc-id:fake
22380     Single-int-var-in-eax/imm32/outputs
22381     0x11/imm32/alloc-id:fake
22382     _string_40_increment_eax/imm32/subx-name
22383     0/imm32/no-rm32
22384     0/imm32/no-r32
22385     0/imm32/no-imm32
22386     0/imm32/no-imm8
22387     0/imm32/no-disp32
22388     0/imm32/no-xm32
22389     0/imm32/no-x32
22390     0x11/imm32/alloc-id:fake
22391     _Primitive-increment-ecx/imm32/next
22392 _Primitive-increment-ecx:  # (payload primitive)
22393     0x11/imm32/alloc-id:fake:payload
22394     # var/ecx <- increment => 41/increment-ecx
22395     0x11/imm32/alloc-id:fake
22396     _string-increment/imm32/name
22397     0/imm32/no-inouts
22398     0/imm32/no-inouts
22399     0x11/imm32/alloc-id:fake
22400     Single-int-var-in-ecx/imm32/outputs
22401     0x11/imm32/alloc-id:fake
22402     _string_41_increment_ecx/imm32/subx-name
22403     0/imm32/no-rm32
22404     0/imm32/no-r32
22405     0/imm32/no-imm32
22406     0/imm32/no-imm8
22407     0/imm32/no-disp32
22408     0/imm32/no-xm32
22409     0/imm32/no-x32
22410     0x11/imm32/alloc-id:fake
22411     _Primitive-increment-edx/imm32/next
22412 _Primitive-increment-edx:  # (payload primitive)
22413     0x11/imm32/alloc-id:fake:payload
22414     # var/edx <- increment => 42/increment-edx
22415     0x11/imm32/alloc-id:fake
22416     _string-increment/imm32/name
22417     0/imm32/no-inouts
22418     0/imm32/no-inouts
22419     0x11/imm32/alloc-id:fake
22420     Single-int-var-in-edx/imm32/outputs
22421     0x11/imm32/alloc-id:fake
22422     _string_42_increment_edx/imm32/subx-name
22423     0/imm32/no-rm32
22424     0/imm32/no-r32
22425     0/imm32/no-imm32
22426     0/imm32/no-imm8
22427     0/imm32/no-disp32
22428     0/imm32/no-xm32
22429     0/imm32/no-x32
22430     0x11/imm32/alloc-id:fake
22431     _Primitive-increment-ebx/imm32/next
22432 _Primitive-increment-ebx:  # (payload primitive)
22433     0x11/imm32/alloc-id:fake:payload
22434     # var/ebx <- increment => 43/increment-ebx
22435     0x11/imm32/alloc-id:fake
22436     _string-increment/imm32/name
22437     0/imm32/no-inouts
22438     0/imm32/no-inouts
22439     0x11/imm32/alloc-id:fake
22440     Single-int-var-in-ebx/imm32/outputs
22441     0x11/imm32/alloc-id:fake
22442     _string_43_increment_ebx/imm32/subx-name
22443     0/imm32/no-rm32
22444     0/imm32/no-r32
22445     0/imm32/no-imm32
22446     0/imm32/no-imm8
22447     0/imm32/no-disp32
22448     0/imm32/no-xm32
22449     0/imm32/no-x32
22450     0x11/imm32/alloc-id:fake
22451     _Primitive-increment-esi/imm32/next
22452 _Primitive-increment-esi:  # (payload primitive)
22453     0x11/imm32/alloc-id:fake:payload
22454     # var/esi <- increment => 46/increment-esi
22455     0x11/imm32/alloc-id:fake
22456     _string-increment/imm32/name
22457     0/imm32/no-inouts
22458     0/imm32/no-inouts
22459     0x11/imm32/alloc-id:fake
22460     Single-int-var-in-esi/imm32/outputs
22461     0x11/imm32/alloc-id:fake
22462     _string_46_increment_esi/imm32/subx-name
22463     0/imm32/no-rm32
22464     0/imm32/no-r32
22465     0/imm32/no-imm32
22466     0/imm32/no-imm8
22467     0/imm32/no-disp32
22468     0/imm32/no-xm32
22469     0/imm32/no-x32
22470     0x11/imm32/alloc-id:fake
22471     _Primitive-increment-edi/imm32/next
22472 _Primitive-increment-edi:  # (payload primitive)
22473     0x11/imm32/alloc-id:fake:payload
22474     # var/edi <- increment => 47/increment-edi
22475     0x11/imm32/alloc-id:fake
22476     _string-increment/imm32/name
22477     0/imm32/no-inouts
22478     0/imm32/no-inouts
22479     0x11/imm32/alloc-id:fake
22480     Single-int-var-in-edi/imm32/outputs
22481     0x11/imm32/alloc-id:fake
22482     _string_47_increment_edi/imm32/subx-name
22483     0/imm32/no-rm32
22484     0/imm32/no-r32
22485     0/imm32/no-imm32
22486     0/imm32/no-imm8
22487     0/imm32/no-disp32
22488     0/imm32/no-xm32
22489     0/imm32/no-x32
22490     0x11/imm32/alloc-id:fake
22491     _Primitive-decrement-eax/imm32/next
22492 _Primitive-decrement-eax:  # (payload primitive)
22493     0x11/imm32/alloc-id:fake:payload
22494     # var/eax <- decrement => 48/decrement-eax
22495     0x11/imm32/alloc-id:fake
22496     _string-decrement/imm32/name
22497     0/imm32/no-inouts
22498     0/imm32/no-inouts
22499     0x11/imm32/alloc-id:fake
22500     Single-int-var-in-eax/imm32/outputs
22501     0x11/imm32/alloc-id:fake
22502     _string_48_decrement_eax/imm32/subx-name
22503     0/imm32/no-rm32
22504     0/imm32/no-r32
22505     0/imm32/no-imm32
22506     0/imm32/no-imm8
22507     0/imm32/no-disp32
22508     0/imm32/no-xm32
22509     0/imm32/no-x32
22510     0x11/imm32/alloc-id:fake
22511     _Primitive-decrement-ecx/imm32/next
22512 _Primitive-decrement-ecx:  # (payload primitive)
22513     0x11/imm32/alloc-id:fake:payload
22514     # var/ecx <- decrement => 49/decrement-ecx
22515     0x11/imm32/alloc-id:fake
22516     _string-decrement/imm32/name
22517     0/imm32/no-inouts
22518     0/imm32/no-inouts
22519     0x11/imm32/alloc-id:fake
22520     Single-int-var-in-ecx/imm32/outputs
22521     0x11/imm32/alloc-id:fake
22522     _string_49_decrement_ecx/imm32/subx-name
22523     0/imm32/no-rm32
22524     0/imm32/no-r32
22525     0/imm32/no-imm32
22526     0/imm32/no-imm8
22527     0/imm32/no-disp32
22528     0/imm32/no-xm32
22529     0/imm32/no-x32
22530     0x11/imm32/alloc-id:fake
22531     _Primitive-decrement-edx/imm32/next
22532 _Primitive-decrement-edx:  # (payload primitive)
22533     0x11/imm32/alloc-id:fake:payload
22534     # var/edx <- decrement => 4a/decrement-edx
22535     0x11/imm32/alloc-id:fake
22536     _string-decrement/imm32/name
22537     0/imm32/no-inouts
22538     0/imm32/no-inouts
22539     0x11/imm32/alloc-id:fake
22540     Single-int-var-in-edx/imm32/outputs
22541     0x11/imm32/alloc-id:fake
22542     _string_4a_decrement_edx/imm32/subx-name
22543     0/imm32/no-rm32
22544     0/imm32/no-r32
22545     0/imm32/no-imm32
22546     0/imm32/no-imm8
22547     0/imm32/no-disp32
22548     0/imm32/no-xm32
22549     0/imm32/no-x32
22550     0x11/imm32/alloc-id:fake
22551     _Primitive-decrement-ebx/imm32/next
22552 _Primitive-decrement-ebx:  # (payload primitive)
22553     0x11/imm32/alloc-id:fake:payload
22554     # var/ebx <- decrement => 4b/decrement-ebx
22555     0x11/imm32/alloc-id:fake
22556     _string-decrement/imm32/name
22557     0/imm32/no-inouts
22558     0/imm32/no-inouts
22559     0x11/imm32/alloc-id:fake
22560     Single-int-var-in-ebx/imm32/outputs
22561     0x11/imm32/alloc-id:fake
22562     _string_4b_decrement_ebx/imm32/subx-name
22563     0/imm32/no-rm32
22564     0/imm32/no-r32
22565     0/imm32/no-imm32
22566     0/imm32/no-imm8
22567     0/imm32/no-disp32
22568     0/imm32/no-xm32
22569     0/imm32/no-x32
22570     0x11/imm32/alloc-id:fake
22571     _Primitive-decrement-esi/imm32/next
22572 _Primitive-decrement-esi:  # (payload primitive)
22573     0x11/imm32/alloc-id:fake:payload
22574     # var/esi <- decrement => 4e/decrement-esi
22575     0x11/imm32/alloc-id:fake
22576     _string-decrement/imm32/name
22577     0/imm32/no-inouts
22578     0/imm32/no-inouts
22579     0x11/imm32/alloc-id:fake
22580     Single-int-var-in-esi/imm32/outputs
22581     0x11/imm32/alloc-id:fake
22582     _string_4e_decrement_esi/imm32/subx-name
22583     0/imm32/no-rm32
22584     0/imm32/no-r32
22585     0/imm32/no-imm32
22586     0/imm32/no-imm8
22587     0/imm32/no-disp32
22588     0/imm32/no-xm32
22589     0/imm32/no-x32
22590     0x11/imm32/alloc-id:fake
22591     _Primitive-decrement-edi/imm32/next
22592 _Primitive-decrement-edi:  # (payload primitive)
22593     0x11/imm32/alloc-id:fake:payload
22594     # var/edi <- decrement => 4f/decrement-edi
22595     0x11/imm32/alloc-id:fake
22596     _string-decrement/imm32/name
22597     0/imm32/no-inouts
22598     0/imm32/no-inouts
22599     0x11/imm32/alloc-id:fake
22600     Single-int-var-in-edi/imm32/outputs
22601     0x11/imm32/alloc-id:fake
22602     _string_4f_decrement_edi/imm32/subx-name
22603     0/imm32/no-rm32
22604     0/imm32/no-r32
22605     0/imm32/no-imm32
22606     0/imm32/no-imm8
22607     0/imm32/no-disp32
22608     0/imm32/no-xm32
22609     0/imm32/no-x32
22610     0x11/imm32/alloc-id:fake
22611     _Primitive-increment-mem/imm32/next
22612 _Primitive-increment-mem:  # (payload primitive)
22613     0x11/imm32/alloc-id:fake:payload
22614     # increment var => ff 0/subop/increment *(ebp+__)
22615     0x11/imm32/alloc-id:fake
22616     _string-increment/imm32/name
22617     0x11/imm32/alloc-id:fake
22618     Single-int-var-in-mem/imm32/inouts
22619     0/imm32/no-outputs
22620     0/imm32/no-outputs
22621     0x11/imm32/alloc-id:fake
22622     _string_ff_subop_increment/imm32/subx-name
22623     1/imm32/rm32-is-first-inout
22624     0/imm32/no-r32
22625     0/imm32/no-imm32
22626     0/imm32/no-imm8
22627     0/imm32/no-disp32
22628     0/imm32/no-xm32
22629     0/imm32/no-x32
22630     0x11/imm32/alloc-id:fake
22631     _Primitive-increment-reg/imm32/next
22632 _Primitive-increment-reg:  # (payload primitive)
22633     0x11/imm32/alloc-id:fake:payload
22634     # var/reg <- increment => ff 0/subop/increment %__
22635     0x11/imm32/alloc-id:fake
22636     _string-increment/imm32/name
22637     0/imm32/no-inouts
22638     0/imm32/no-inouts
22639     0x11/imm32/alloc-id:fake
22640     Single-int-var-in-some-register/imm32/outputs
22641     0x11/imm32/alloc-id:fake
22642     _string_ff_subop_increment/imm32/subx-name
22643     3/imm32/rm32-is-first-output
22644     0/imm32/no-r32
22645     0/imm32/no-imm32
22646     0/imm32/no-imm8
22647     0/imm32/no-disp32
22648     0/imm32/no-xm32
22649     0/imm32/no-x32
22650     0x11/imm32/alloc-id:fake
22651     _Primitive-decrement-mem/imm32/next
22652 _Primitive-decrement-mem:  # (payload primitive)
22653     0x11/imm32/alloc-id:fake:payload
22654     # decrement var => ff 1/subop/decrement *(ebp+__)
22655     0x11/imm32/alloc-id:fake
22656     _string-decrement/imm32/name
22657     0x11/imm32/alloc-id:fake
22658     Single-int-var-in-mem/imm32/inouts
22659     0/imm32/no-outputs
22660     0/imm32/no-outputs
22661     0x11/imm32/alloc-id:fake
22662     _string_ff_subop_decrement/imm32/subx-name
22663     1/imm32/rm32-is-first-inout
22664     0/imm32/no-r32
22665     0/imm32/no-imm32
22666     0/imm32/no-imm8
22667     0/imm32/no-disp32
22668     0/imm32/no-xm32
22669     0/imm32/no-x32
22670     0x11/imm32/alloc-id:fake
22671     _Primitive-decrement-reg/imm32/next
22672 _Primitive-decrement-reg:  # (payload primitive)
22673     0x11/imm32/alloc-id:fake:payload
22674     # var/reg <- decrement => ff 1/subop/decrement %__
22675     0x11/imm32/alloc-id:fake
22676     _string-decrement/imm32/name
22677     0/imm32/no-inouts
22678     0/imm32/no-inouts
22679     0x11/imm32/alloc-id:fake
22680     Single-int-var-in-some-register/imm32/outputs
22681     0x11/imm32/alloc-id:fake
22682     _string_ff_subop_decrement/imm32/subx-name
22683     3/imm32/rm32-is-first-output
22684     0/imm32/no-r32
22685     0/imm32/no-imm32
22686     0/imm32/no-imm8
22687     0/imm32/no-disp32
22688     0/imm32/no-xm32
22689     0/imm32/no-x32
22690     0x11/imm32/alloc-id:fake
22691     _Primitive-add-to-eax/imm32/next
22692 # - add
22693 _Primitive-add-to-eax:  # (payload primitive)
22694     0x11/imm32/alloc-id:fake:payload
22695     # var/eax <- add lit => 05/add-to-eax lit/imm32
22696     0x11/imm32/alloc-id:fake
22697     _string-add/imm32/name
22698     0x11/imm32/alloc-id:fake
22699     Single-lit-var/imm32/inouts
22700     0x11/imm32/alloc-id:fake
22701     Single-int-var-in-eax/imm32/outputs
22702     0x11/imm32/alloc-id:fake
22703     _string_05_add_to_eax/imm32/subx-name
22704     0/imm32/no-rm32
22705     0/imm32/no-r32
22706     1/imm32/imm32-is-first-inout
22707     0/imm32/no-imm8
22708     0/imm32/no-disp32
22709     0/imm32/no-xm32
22710     0/imm32/no-x32
22711     0x11/imm32/alloc-id:fake
22712     _Primitive-add-reg-to-reg/imm32/next
22713 _Primitive-add-reg-to-reg:  # (payload primitive)
22714     0x11/imm32/alloc-id:fake:payload
22715     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
22716     0x11/imm32/alloc-id:fake
22717     _string-add/imm32/name
22718     0x11/imm32/alloc-id:fake
22719     Single-int-var-in-some-register/imm32/inouts
22720     0x11/imm32/alloc-id:fake
22721     Single-int-var-in-some-register/imm32/outputs
22722     0x11/imm32/alloc-id:fake
22723     _string_01_add_to/imm32/subx-name
22724     3/imm32/rm32-is-first-output
22725     1/imm32/r32-is-first-inout
22726     0/imm32/no-imm32
22727     0/imm32/no-imm8
22728     0/imm32/no-disp32
22729     0/imm32/no-xm32
22730     0/imm32/no-x32
22731     0x11/imm32/alloc-id:fake
22732     _Primitive-add-reg-to-mem/imm32/next
22733 _Primitive-add-reg-to-mem:  # (payload primitive)
22734     0x11/imm32/alloc-id:fake:payload
22735     # add-to var1 var2/reg => 01/add-to var1 var2/r32
22736     0x11/imm32/alloc-id:fake
22737     _string-add-to/imm32/name
22738     0x11/imm32/alloc-id:fake
22739     Two-args-int-stack-int-reg/imm32/inouts
22740     0/imm32/no-outputs
22741     0/imm32/no-outputs
22742     0x11/imm32/alloc-id:fake
22743     _string_01_add_to/imm32/subx-name
22744     1/imm32/rm32-is-first-inout
22745     2/imm32/r32-is-second-inout
22746     0/imm32/no-imm32
22747     0/imm32/no-imm8
22748     0/imm32/no-disp32
22749     0/imm32/no-xm32
22750     0/imm32/no-x32
22751     0x11/imm32/alloc-id:fake
22752     _Primitive-add-mem-to-reg/imm32/next
22753 _Primitive-add-mem-to-reg:  # (payload primitive)
22754     0x11/imm32/alloc-id:fake:payload
22755     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
22756     0x11/imm32/alloc-id:fake
22757     _string-add/imm32/name
22758     0x11/imm32/alloc-id:fake
22759     Single-int-var-in-mem/imm32/inouts
22760     0x11/imm32/alloc-id:fake
22761     Single-int-var-in-some-register/imm32/outputs
22762     0x11/imm32/alloc-id:fake
22763     _string_03_add/imm32/subx-name
22764     1/imm32/rm32-is-first-inout
22765     3/imm32/r32-is-first-output
22766     0/imm32/no-imm32
22767     0/imm32/no-imm8
22768     0/imm32/no-disp32
22769     0/imm32/no-xm32
22770     0/imm32/no-x32
22771     0x11/imm32/alloc-id:fake
22772     _Primitive-add-lit-to-reg/imm32/next
22773 _Primitive-add-lit-to-reg:  # (payload primitive)
22774     0x11/imm32/alloc-id:fake:payload
22775     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
22776     0x11/imm32/alloc-id:fake
22777     _string-add/imm32/name
22778     0x11/imm32/alloc-id:fake
22779     Single-lit-var/imm32/inouts
22780     0x11/imm32/alloc-id:fake
22781     Single-int-var-in-some-register/imm32/outputs
22782     0x11/imm32/alloc-id:fake
22783     _string_81_subop_add/imm32/subx-name
22784     3/imm32/rm32-is-first-output
22785     0/imm32/no-r32
22786     1/imm32/imm32-is-first-inout
22787     0/imm32/no-imm8
22788     0/imm32/no-disp32
22789     0/imm32/no-xm32
22790     0/imm32/no-x32
22791     0x11/imm32/alloc-id:fake
22792     _Primitive-add-lit-to-mem/imm32/next
22793 _Primitive-add-lit-to-mem:  # (payload primitive)
22794     0x11/imm32/alloc-id:fake:payload
22795     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
22796     0x11/imm32/alloc-id:fake
22797     _string-add-to/imm32/name
22798     0x11/imm32/alloc-id:fake
22799     Int-var-and-literal/imm32/inouts
22800     0/imm32/no-outputs
22801     0/imm32/no-outputs
22802     0x11/imm32/alloc-id:fake
22803     _string_81_subop_add/imm32/subx-name
22804     1/imm32/rm32-is-first-inout
22805     0/imm32/no-r32
22806     2/imm32/imm32-is-second-inout
22807     0/imm32/no-imm8
22808     0/imm32/no-disp32
22809     0/imm32/no-xm32
22810     0/imm32/no-x32
22811     0x11/imm32/alloc-id:fake
22812     _Primitive-subtract-from-eax/imm32/next
22813 # - subtract
22814 _Primitive-subtract-from-eax:  # (payload primitive)
22815     0x11/imm32/alloc-id:fake:payload
22816     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
22817     0x11/imm32/alloc-id:fake
22818     _string-subtract/imm32/name
22819     0x11/imm32/alloc-id:fake
22820     Single-lit-var/imm32/inouts
22821     0x11/imm32/alloc-id:fake
22822     Single-int-var-in-eax/imm32/outputs
22823     0x11/imm32/alloc-id:fake
22824     _string_2d_subtract_from_eax/imm32/subx-name
22825     0/imm32/no-rm32
22826     0/imm32/no-r32
22827     1/imm32/imm32-is-first-inout
22828     0/imm32/no-imm8
22829     0/imm32/no-disp32
22830     0/imm32/no-xm32
22831     0/imm32/no-x32
22832     0x11/imm32/alloc-id:fake
22833     _Primitive-subtract-reg-from-reg/imm32/next
22834 _Primitive-subtract-reg-from-reg:  # (payload primitive)
22835     0x11/imm32/alloc-id:fake:payload
22836     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
22837     0x11/imm32/alloc-id:fake
22838     _string-subtract/imm32/name
22839     0x11/imm32/alloc-id:fake
22840     Single-int-var-in-some-register/imm32/inouts
22841     0x11/imm32/alloc-id:fake
22842     Single-int-var-in-some-register/imm32/outputs
22843     0x11/imm32/alloc-id:fake
22844     _string_29_subtract_from/imm32/subx-name
22845     3/imm32/rm32-is-first-output
22846     1/imm32/r32-is-first-inout
22847     0/imm32/no-imm32
22848     0/imm32/no-imm8
22849     0/imm32/no-disp32
22850     0/imm32/no-xm32
22851     0/imm32/no-x32
22852     0x11/imm32/alloc-id:fake
22853     _Primitive-subtract-reg-from-mem/imm32/next
22854 _Primitive-subtract-reg-from-mem:  # (payload primitive)
22855     0x11/imm32/alloc-id:fake:payload
22856     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
22857     0x11/imm32/alloc-id:fake
22858     _string-subtract-from/imm32/name
22859     0x11/imm32/alloc-id:fake
22860     Two-args-int-stack-int-reg/imm32/inouts
22861     0/imm32/no-outputs
22862     0/imm32/no-outputs
22863     0x11/imm32/alloc-id:fake
22864     _string_29_subtract_from/imm32/subx-name
22865     1/imm32/rm32-is-first-inout
22866     2/imm32/r32-is-second-inout
22867     0/imm32/no-imm32
22868     0/imm32/no-imm8
22869     0/imm32/no-disp32
22870     0/imm32/no-xm32
22871     0/imm32/no-x32
22872     0x11/imm32/alloc-id:fake
22873     _Primitive-subtract-mem-from-reg/imm32/next
22874 _Primitive-subtract-mem-from-reg:  # (payload primitive)
22875     0x11/imm32/alloc-id:fake:payload
22876     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
22877     0x11/imm32/alloc-id:fake
22878     _string-subtract/imm32/name
22879     0x11/imm32/alloc-id:fake
22880     Single-int-var-in-mem/imm32/inouts
22881     0x11/imm32/alloc-id:fake
22882     Single-int-var-in-some-register/imm32/outputs
22883     0x11/imm32/alloc-id:fake
22884     _string_2b_subtract/imm32/subx-name
22885     1/imm32/rm32-is-first-inout
22886     3/imm32/r32-is-first-output
22887     0/imm32/no-imm32
22888     0/imm32/no-imm8
22889     0/imm32/no-disp32
22890     0/imm32/no-xm32
22891     0/imm32/no-x32
22892     0x11/imm32/alloc-id:fake
22893     _Primitive-subtract-lit-from-reg/imm32/next
22894 _Primitive-subtract-lit-from-reg:  # (payload primitive)
22895     0x11/imm32/alloc-id:fake:payload
22896     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
22897     0x11/imm32/alloc-id:fake
22898     _string-subtract/imm32/name
22899     0x11/imm32/alloc-id:fake
22900     Single-lit-var/imm32/inouts
22901     0x11/imm32/alloc-id:fake
22902     Single-int-var-in-some-register/imm32/outputs
22903     0x11/imm32/alloc-id:fake
22904     _string_81_subop_subtract/imm32/subx-name
22905     3/imm32/rm32-is-first-output
22906     0/imm32/no-r32
22907     1/imm32/imm32-is-first-inout
22908     0/imm32/no-imm8
22909     0/imm32/no-disp32
22910     0/imm32/no-xm32
22911     0/imm32/no-x32
22912     0x11/imm32/alloc-id:fake
22913     _Primitive-subtract-lit-from-mem/imm32/next
22914 _Primitive-subtract-lit-from-mem:  # (payload primitive)
22915     0x11/imm32/alloc-id:fake:payload
22916     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
22917     0x11/imm32/alloc-id:fake
22918     _string-subtract-from/imm32/name
22919     0x11/imm32/alloc-id:fake
22920     Int-var-and-literal/imm32/inouts
22921     0/imm32/no-outputs
22922     0/imm32/no-outputs
22923     0x11/imm32/alloc-id:fake
22924     _string_81_subop_subtract/imm32/subx-name
22925     1/imm32/rm32-is-first-inout
22926     0/imm32/no-r32
22927     2/imm32/imm32-is-second-inout
22928     0/imm32/no-imm8
22929     0/imm32/no-disp32
22930     0/imm32/no-xm32
22931     0/imm32/no-x32
22932     0x11/imm32/alloc-id:fake
22933     _Primitive-and-with-eax/imm32/next
22934 # - and
22935 _Primitive-and-with-eax:  # (payload primitive)
22936     0x11/imm32/alloc-id:fake:payload
22937     # var/eax <- and lit => 25/and-with-eax lit/imm32
22938     0x11/imm32/alloc-id:fake
22939     _string-and/imm32/name
22940     0x11/imm32/alloc-id:fake
22941     Single-lit-var/imm32/inouts
22942     0x11/imm32/alloc-id:fake
22943     Single-int-var-in-eax/imm32/outputs
22944     0x11/imm32/alloc-id:fake
22945     _string_25_and_with_eax/imm32/subx-name
22946     0/imm32/no-rm32
22947     0/imm32/no-r32
22948     1/imm32/imm32-is-first-inout
22949     0/imm32/no-imm8
22950     0/imm32/no-disp32
22951     0/imm32/no-xm32
22952     0/imm32/no-x32
22953     0x11/imm32/alloc-id:fake
22954     _Primitive-and-reg-with-reg/imm32/next
22955 _Primitive-and-reg-with-reg:  # (payload primitive)
22956     0x11/imm32/alloc-id:fake:payload
22957     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
22958     0x11/imm32/alloc-id:fake
22959     _string-and/imm32/name
22960     0x11/imm32/alloc-id:fake
22961     Single-int-var-in-some-register/imm32/inouts
22962     0x11/imm32/alloc-id:fake
22963     Single-int-var-in-some-register/imm32/outputs
22964     0x11/imm32/alloc-id:fake
22965     _string_21_and_with/imm32/subx-name
22966     3/imm32/rm32-is-first-output
22967     1/imm32/r32-is-first-inout
22968     0/imm32/no-imm32
22969     0/imm32/no-imm8
22970     0/imm32/no-disp32
22971     0/imm32/no-xm32
22972     0/imm32/no-x32
22973     0x11/imm32/alloc-id:fake
22974     _Primitive-and-reg-with-mem/imm32/next
22975 _Primitive-and-reg-with-mem:  # (payload primitive)
22976     0x11/imm32/alloc-id:fake:payload
22977     # and-with var1 var2/reg => 21/and-with var1 var2/r32
22978     0x11/imm32/alloc-id:fake
22979     _string-and-with/imm32/name
22980     0x11/imm32/alloc-id:fake
22981     Two-args-int-stack-int-reg/imm32/inouts
22982     0/imm32/no-outputs
22983     0/imm32/no-outputs
22984     0x11/imm32/alloc-id:fake
22985     _string_21_and_with/imm32/subx-name
22986     1/imm32/rm32-is-first-inout
22987     2/imm32/r32-is-second-inout
22988     0/imm32/no-imm32
22989     0/imm32/no-imm8
22990     0/imm32/no-disp32
22991     0/imm32/no-xm32
22992     0/imm32/no-x32
22993     0x11/imm32/alloc-id:fake
22994     _Primitive-and-mem-with-reg/imm32/next
22995 _Primitive-and-mem-with-reg:  # (payload primitive)
22996     0x11/imm32/alloc-id:fake:payload
22997     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
22998     0x11/imm32/alloc-id:fake
22999     _string-and/imm32/name
23000     0x11/imm32/alloc-id:fake
23001     Single-int-var-in-mem/imm32/inouts
23002     0x11/imm32/alloc-id:fake
23003     Single-int-var-in-some-register/imm32/outputs
23004     0x11/imm32/alloc-id:fake
23005     _string_23_and/imm32/subx-name
23006     1/imm32/rm32-is-first-inout
23007     3/imm32/r32-is-first-output
23008     0/imm32/no-imm32
23009     0/imm32/no-imm8
23010     0/imm32/no-disp32
23011     0/imm32/no-xm32
23012     0/imm32/no-x32
23013     0x11/imm32/alloc-id:fake
23014     _Primitive-and-lit-with-reg/imm32/next
23015 _Primitive-and-lit-with-reg:  # (payload primitive)
23016     0x11/imm32/alloc-id:fake:payload
23017     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
23018     0x11/imm32/alloc-id:fake
23019     _string-and/imm32/name
23020     0x11/imm32/alloc-id:fake
23021     Single-lit-var/imm32/inouts
23022     0x11/imm32/alloc-id:fake
23023     Single-int-var-in-some-register/imm32/outputs
23024     0x11/imm32/alloc-id:fake
23025     _string_81_subop_and/imm32/subx-name
23026     3/imm32/rm32-is-first-output
23027     0/imm32/no-r32
23028     1/imm32/imm32-is-first-inout
23029     0/imm32/no-imm8
23030     0/imm32/no-disp32
23031     0/imm32/no-xm32
23032     0/imm32/no-x32
23033     0x11/imm32/alloc-id:fake
23034     _Primitive-and-lit-with-mem/imm32/next
23035 _Primitive-and-lit-with-mem:  # (payload primitive)
23036     0x11/imm32/alloc-id:fake:payload
23037     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
23038     0x11/imm32/alloc-id:fake
23039     _string-and-with/imm32/name
23040     0x11/imm32/alloc-id:fake
23041     Int-var-and-literal/imm32/inouts
23042     0/imm32/no-outputs
23043     0/imm32/no-outputs
23044     0x11/imm32/alloc-id:fake
23045     _string_81_subop_and/imm32/subx-name
23046     1/imm32/rm32-is-first-inout
23047     0/imm32/no-r32
23048     2/imm32/imm32-is-second-inout
23049     0/imm32/no-imm8
23050     0/imm32/no-disp32
23051     0/imm32/no-xm32
23052     0/imm32/no-x32
23053     0x11/imm32/alloc-id:fake
23054     _Primitive-or-with-eax/imm32/next
23055 # - or
23056 _Primitive-or-with-eax:  # (payload primitive)
23057     0x11/imm32/alloc-id:fake:payload
23058     # var/eax <- or lit => 0d/or-with-eax lit/imm32
23059     0x11/imm32/alloc-id:fake
23060     _string-or/imm32/name
23061     0x11/imm32/alloc-id:fake
23062     Single-lit-var/imm32/inouts
23063     0x11/imm32/alloc-id:fake
23064     Single-int-var-in-eax/imm32/outputs
23065     0x11/imm32/alloc-id:fake
23066     _string_0d_or_with_eax/imm32/subx-name
23067     0/imm32/no-rm32
23068     0/imm32/no-r32
23069     1/imm32/imm32-is-first-inout
23070     0/imm32/no-imm8
23071     0/imm32/no-disp32
23072     0/imm32/no-xm32
23073     0/imm32/no-x32
23074     0x11/imm32/alloc-id:fake
23075     _Primitive-or-reg-with-reg/imm32/next
23076 _Primitive-or-reg-with-reg:  # (payload primitive)
23077     0x11/imm32/alloc-id:fake:payload
23078     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
23079     0x11/imm32/alloc-id:fake
23080     _string-or/imm32/name
23081     0x11/imm32/alloc-id:fake
23082     Single-int-var-in-some-register/imm32/inouts
23083     0x11/imm32/alloc-id:fake
23084     Single-int-var-in-some-register/imm32/outputs
23085     0x11/imm32/alloc-id:fake
23086     _string_09_or_with/imm32/subx-name
23087     3/imm32/rm32-is-first-output
23088     1/imm32/r32-is-first-inout
23089     0/imm32/no-imm32
23090     0/imm32/no-imm8
23091     0/imm32/no-disp32
23092     0/imm32/no-xm32
23093     0/imm32/no-x32
23094     0x11/imm32/alloc-id:fake
23095     _Primitive-or-reg-with-mem/imm32/next
23096 _Primitive-or-reg-with-mem:  # (payload primitive)
23097     0x11/imm32/alloc-id:fake:payload
23098     # or-with var1 var2/reg => 09/or-with var1 var2/r32
23099     0x11/imm32/alloc-id:fake
23100     _string-or-with/imm32/name
23101     0x11/imm32/alloc-id:fake
23102     Two-args-int-stack-int-reg/imm32/inouts
23103     0/imm32/no-outputs
23104     0/imm32/no-outputs
23105     0x11/imm32/alloc-id:fake
23106     _string_09_or_with/imm32/subx-name
23107     1/imm32/rm32-is-first-inout
23108     2/imm32/r32-is-second-inout
23109     0/imm32/no-imm32
23110     0/imm32/no-imm8
23111     0/imm32/no-disp32
23112     0/imm32/no-xm32
23113     0/imm32/no-x32
23114     0x11/imm32/alloc-id:fake
23115     _Primitive-or-mem-with-reg/imm32/next
23116 _Primitive-or-mem-with-reg:  # (payload primitive)
23117     0x11/imm32/alloc-id:fake:payload
23118     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
23119     0x11/imm32/alloc-id:fake
23120     _string-or/imm32/name
23121     0x11/imm32/alloc-id:fake
23122     Single-int-var-in-mem/imm32/inouts
23123     0x11/imm32/alloc-id:fake
23124     Single-int-var-in-some-register/imm32/outputs
23125     0x11/imm32/alloc-id:fake
23126     _string_0b_or/imm32/subx-name
23127     1/imm32/rm32-is-first-inout
23128     3/imm32/r32-is-first-output
23129     0/imm32/no-imm32
23130     0/imm32/no-imm8
23131     0/imm32/no-disp32
23132     0/imm32/no-xm32
23133     0/imm32/no-x32
23134     0x11/imm32/alloc-id:fake
23135     _Primitive-or-lit-with-reg/imm32/next
23136 _Primitive-or-lit-with-reg:  # (payload primitive)
23137     0x11/imm32/alloc-id:fake:payload
23138     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
23139     0x11/imm32/alloc-id:fake
23140     _string-or/imm32/name
23141     0x11/imm32/alloc-id:fake
23142     Single-lit-var/imm32/inouts
23143     0x11/imm32/alloc-id:fake
23144     Single-int-var-in-some-register/imm32/outputs
23145     0x11/imm32/alloc-id:fake
23146     _string_81_subop_or/imm32/subx-name
23147     3/imm32/rm32-is-first-output
23148     0/imm32/no-r32
23149     1/imm32/imm32-is-first-inout
23150     0/imm32/no-imm8
23151     0/imm32/no-disp32
23152     0/imm32/no-xm32
23153     0/imm32/no-x32
23154     0x11/imm32/alloc-id:fake
23155     _Primitive-or-lit-with-mem/imm32/next
23156 _Primitive-or-lit-with-mem:  # (payload primitive)
23157     0x11/imm32/alloc-id:fake:payload
23158     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
23159     0x11/imm32/alloc-id:fake
23160     _string-or-with/imm32/name
23161     0x11/imm32/alloc-id:fake
23162     Int-var-and-literal/imm32/inouts
23163     0/imm32/no-outputs
23164     0/imm32/no-outputs
23165     0x11/imm32/alloc-id:fake
23166     _string_81_subop_or/imm32/subx-name
23167     1/imm32/rm32-is-first-inout
23168     0/imm32/no-r32
23169     2/imm32/imm32-is-second-inout
23170     0/imm32/no-imm8
23171     0/imm32/no-disp32
23172     0/imm32/no-xm32
23173     0/imm32/no-x32
23174     0x11/imm32/alloc-id:fake
23175     _Primitive-xor-with-eax/imm32/next
23176 # - xor
23177 _Primitive-xor-with-eax:  # (payload primitive)
23178     0x11/imm32/alloc-id:fake:payload
23179     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
23180     0x11/imm32/alloc-id:fake
23181     _string-xor/imm32/name
23182     0x11/imm32/alloc-id:fake
23183     Single-lit-var/imm32/inouts
23184     0x11/imm32/alloc-id:fake
23185     Single-int-var-in-eax/imm32/outputs
23186     0x11/imm32/alloc-id:fake
23187     _string_35_xor_with_eax/imm32/subx-name
23188     0/imm32/no-rm32
23189     0/imm32/no-r32
23190     1/imm32/imm32-is-first-inout
23191     0/imm32/no-imm8
23192     0/imm32/no-disp32
23193     0/imm32/no-xm32
23194     0/imm32/no-x32
23195     0x11/imm32/alloc-id:fake
23196     _Primitive-xor-reg-with-reg/imm32/next
23197 _Primitive-xor-reg-with-reg:  # (payload primitive)
23198     0x11/imm32/alloc-id:fake:payload
23199     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
23200     0x11/imm32/alloc-id:fake
23201     _string-xor/imm32/name
23202     0x11/imm32/alloc-id:fake
23203     Single-int-var-in-some-register/imm32/inouts
23204     0x11/imm32/alloc-id:fake
23205     Single-int-var-in-some-register/imm32/outputs
23206     0x11/imm32/alloc-id:fake
23207     _string_31_xor_with/imm32/subx-name
23208     3/imm32/rm32-is-first-output
23209     1/imm32/r32-is-first-inout
23210     0/imm32/no-imm32
23211     0/imm32/no-imm8
23212     0/imm32/no-disp32
23213     0/imm32/no-xm32
23214     0/imm32/no-x32
23215     0x11/imm32/alloc-id:fake
23216     _Primitive-xor-reg-with-mem/imm32/next
23217 _Primitive-xor-reg-with-mem:  # (payload primitive)
23218     0x11/imm32/alloc-id:fake:payload
23219     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
23220     0x11/imm32/alloc-id:fake
23221     _string-xor-with/imm32/name
23222     0x11/imm32/alloc-id:fake
23223     Two-args-int-stack-int-reg/imm32/inouts
23224     0/imm32/no-outputs
23225     0/imm32/no-outputs
23226     0x11/imm32/alloc-id:fake
23227     _string_31_xor_with/imm32/subx-name
23228     1/imm32/rm32-is-first-inout
23229     2/imm32/r32-is-second-inout
23230     0/imm32/no-imm32
23231     0/imm32/no-imm8
23232     0/imm32/no-disp32
23233     0/imm32/no-xm32
23234     0/imm32/no-x32
23235     0x11/imm32/alloc-id:fake
23236     _Primitive-xor-mem-with-reg/imm32/next
23237 _Primitive-xor-mem-with-reg:  # (payload primitive)
23238     0x11/imm32/alloc-id:fake:payload
23239     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
23240     0x11/imm32/alloc-id:fake
23241     _string-xor/imm32/name
23242     0x11/imm32/alloc-id:fake
23243     Single-int-var-in-mem/imm32/inouts
23244     0x11/imm32/alloc-id:fake
23245     Single-int-var-in-some-register/imm32/outputs
23246     0x11/imm32/alloc-id:fake
23247     _string_33_xor/imm32/subx-name
23248     1/imm32/rm32-is-first-inout
23249     3/imm32/r32-is-first-output
23250     0/imm32/no-imm32
23251     0/imm32/no-imm8
23252     0/imm32/no-disp32
23253     0/imm32/no-xm32
23254     0/imm32/no-x32
23255     0x11/imm32/alloc-id:fake
23256     _Primitive-xor-lit-with-reg/imm32/next
23257 _Primitive-xor-lit-with-reg:  # (payload primitive)
23258     0x11/imm32/alloc-id:fake:payload
23259     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
23260     0x11/imm32/alloc-id:fake
23261     _string-xor/imm32/name
23262     0x11/imm32/alloc-id:fake
23263     Single-lit-var/imm32/inouts
23264     0x11/imm32/alloc-id:fake
23265     Single-int-var-in-some-register/imm32/outputs
23266     0x11/imm32/alloc-id:fake
23267     _string_81_subop_xor/imm32/subx-name
23268     3/imm32/rm32-is-first-output
23269     0/imm32/no-r32
23270     1/imm32/imm32-is-first-inout
23271     0/imm32/no-imm8
23272     0/imm32/no-disp32
23273     0/imm32/no-xm32
23274     0/imm32/no-x32
23275     0x11/imm32/alloc-id:fake
23276     _Primitive-xor-lit-with-mem/imm32/next
23277 _Primitive-xor-lit-with-mem:  # (payload primitive)
23278     0x11/imm32/alloc-id:fake:payload
23279     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
23280     0x11/imm32/alloc-id:fake
23281     _string-xor-with/imm32/name
23282     0x11/imm32/alloc-id:fake
23283     Int-var-and-literal/imm32/inouts
23284     0/imm32/no-outputs
23285     0/imm32/no-outputs
23286     0x11/imm32/alloc-id:fake
23287     _string_81_subop_xor/imm32/subx-name
23288     1/imm32/rm32-is-first-inout
23289     0/imm32/no-r32
23290     2/imm32/imm32-is-second-inout
23291     0/imm32/no-imm8
23292     0/imm32/no-disp32
23293     0/imm32/no-xm32
23294     0/imm32/no-x32
23295     0x11/imm32/alloc-id:fake
23296     _Primitive-shift-reg-left-by-lit/imm32/next
23297 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
23298     0x11/imm32/alloc-id:fake:payload
23299     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
23300     0x11/imm32/alloc-id:fake
23301     _string-shift-left/imm32/name
23302     0x11/imm32/alloc-id:fake
23303     Single-lit-var/imm32/inouts
23304     0x11/imm32/alloc-id:fake
23305     Single-int-var-in-some-register/imm32/outputs
23306     0x11/imm32/alloc-id:fake
23307     _string_c1_subop_shift_left/imm32/subx-name
23308     3/imm32/rm32-is-first-output
23309     0/imm32/no-r32
23310     0/imm32/no-imm32
23311     1/imm32/imm8-is-first-inout
23312     0/imm32/no-disp32
23313     0/imm32/no-xm32
23314     0/imm32/no-x32
23315     0x11/imm32/alloc-id:fake
23316     _Primitive-shift-reg-right-by-lit/imm32/next
23317 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
23318     0x11/imm32/alloc-id:fake:payload
23319     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
23320     0x11/imm32/alloc-id:fake
23321     _string-shift-right/imm32/name
23322     0x11/imm32/alloc-id:fake
23323     Single-lit-var/imm32/inouts
23324     0x11/imm32/alloc-id:fake
23325     Single-int-var-in-some-register/imm32/outputs
23326     0x11/imm32/alloc-id:fake
23327     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
23328     3/imm32/rm32-is-first-output
23329     0/imm32/no-r32
23330     0/imm32/no-imm32
23331     1/imm32/imm8-is-first-inout
23332     0/imm32/no-disp32
23333     0/imm32/no-xm32
23334     0/imm32/no-x32
23335     0x11/imm32/alloc-id:fake
23336     _Primitive-shift-reg-right-signed-by-lit/imm32/next
23337 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
23338     0x11/imm32/alloc-id:fake:payload
23339     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
23340     0x11/imm32/alloc-id:fake
23341     _string-shift-right-signed/imm32/name
23342     0x11/imm32/alloc-id:fake
23343     Single-lit-var/imm32/inouts
23344     0x11/imm32/alloc-id:fake
23345     Single-int-var-in-some-register/imm32/outputs
23346     0x11/imm32/alloc-id:fake
23347     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
23348     3/imm32/rm32-is-first-output
23349     0/imm32/no-r32
23350     0/imm32/no-imm32
23351     1/imm32/imm8-is-first-inout
23352     0/imm32/no-disp32
23353     0/imm32/no-xm32
23354     0/imm32/no-x32
23355     0x11/imm32/alloc-id:fake
23356     _Primitive-shift-mem-left-by-lit/imm32/next
23357 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
23358     0x11/imm32/alloc-id:fake:payload
23359     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
23360     0x11/imm32/alloc-id:fake
23361     _string-shift-left/imm32/name
23362     0x11/imm32/alloc-id:fake
23363     Int-var-and-literal/imm32/inouts
23364     0/imm32/no-outputs
23365     0/imm32/no-outputs
23366     0x11/imm32/alloc-id:fake
23367     _string_c1_subop_shift_left/imm32/subx-name
23368     1/imm32/rm32-is-first-inout
23369     0/imm32/no-r32
23370     0/imm32/no-imm32
23371     2/imm32/imm8-is-second-inout
23372     0/imm32/no-disp32
23373     0/imm32/no-xm32
23374     0/imm32/no-x32
23375     0x11/imm32/alloc-id:fake
23376     _Primitive-shift-mem-right-by-lit/imm32/next
23377 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
23378     0x11/imm32/alloc-id:fake:payload
23379     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
23380     0x11/imm32/alloc-id:fake
23381     _string-shift-right/imm32/name
23382     0x11/imm32/alloc-id:fake
23383     Int-var-and-literal/imm32/inouts
23384     0/imm32/no-outputs
23385     0/imm32/no-outputs
23386     0x11/imm32/alloc-id:fake
23387     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
23388     1/imm32/rm32-is-first-inout
23389     0/imm32/no-r32
23390     0/imm32/no-imm32
23391     2/imm32/imm8-is-second-inout
23392     0/imm32/no-disp32
23393     0/imm32/no-xm32
23394     0/imm32/no-x32
23395     0x11/imm32/alloc-id:fake
23396     _Primitive-shift-mem-right-signed-by-lit/imm32/next
23397 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
23398     0x11/imm32/alloc-id:fake:payload
23399     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
23400     0x11/imm32/alloc-id:fake
23401     _string-shift-right-signed/imm32/name
23402     0x11/imm32/alloc-id:fake
23403     Int-var-and-literal/imm32/inouts
23404     0/imm32/no-outputs
23405     0/imm32/no-outputs
23406     0x11/imm32/alloc-id:fake
23407     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
23408     1/imm32/rm32-is-first-inout
23409     0/imm32/no-r32
23410     0/imm32/no-imm32
23411     2/imm32/imm8-is-second-inout
23412     0/imm32/no-disp32
23413     0/imm32/no-xm32
23414     0/imm32/no-x32
23415     0x11/imm32/alloc-id:fake
23416     _Primitive-copy-to-eax/imm32/next
23417 # - copy
23418 _Primitive-copy-to-eax:  # (payload primitive)
23419     0x11/imm32/alloc-id:fake:payload
23420     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
23421     0x11/imm32/alloc-id:fake
23422     _string-copy/imm32/name
23423     0x11/imm32/alloc-id:fake
23424     Single-lit-var/imm32/inouts
23425     0x11/imm32/alloc-id:fake
23426     Single-int-var-in-eax/imm32/outputs
23427     0x11/imm32/alloc-id:fake
23428     _string_b8_copy_to_eax/imm32/subx-name
23429     0/imm32/no-rm32
23430     0/imm32/no-r32
23431     1/imm32/imm32-is-first-inout
23432     0/imm32/no-imm8
23433     0/imm32/no-disp32
23434     0/imm32/no-xm32
23435     0/imm32/no-x32
23436     0x11/imm32/alloc-id:fake
23437     _Primitive-copy-to-ecx/imm32/next
23438 _Primitive-copy-to-ecx:  # (payload primitive)
23439     0x11/imm32/alloc-id:fake:payload
23440     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
23441     0x11/imm32/alloc-id:fake
23442     _string-copy/imm32/name
23443     0x11/imm32/alloc-id:fake
23444     Single-lit-var/imm32/inouts
23445     0x11/imm32/alloc-id:fake
23446     Single-int-var-in-ecx/imm32/outputs
23447     0x11/imm32/alloc-id:fake
23448     _string_b9_copy_to_ecx/imm32/subx-name
23449     0/imm32/no-rm32
23450     0/imm32/no-r32
23451     1/imm32/imm32-is-first-inout
23452     0/imm32/no-imm8
23453     0/imm32/no-disp32
23454     0/imm32/no-xm32
23455     0/imm32/no-x32
23456     0x11/imm32/alloc-id:fake
23457     _Primitive-copy-to-edx/imm32/next
23458 _Primitive-copy-to-edx:  # (payload primitive)
23459     0x11/imm32/alloc-id:fake:payload
23460     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
23461     0x11/imm32/alloc-id:fake
23462     _string-copy/imm32/name
23463     0x11/imm32/alloc-id:fake
23464     Single-lit-var/imm32/inouts
23465     0x11/imm32/alloc-id:fake
23466     Single-int-var-in-edx/imm32/outputs
23467     0x11/imm32/alloc-id:fake
23468     _string_ba_copy_to_edx/imm32/subx-name
23469     0/imm32/no-rm32
23470     0/imm32/no-r32
23471     1/imm32/imm32-is-first-inout
23472     0/imm32/no-imm8
23473     0/imm32/no-disp32
23474     0/imm32/no-xm32
23475     0/imm32/no-x32
23476     0x11/imm32/alloc-id:fake
23477     _Primitive-copy-to-ebx/imm32/next
23478 _Primitive-copy-to-ebx:  # (payload primitive)
23479     0x11/imm32/alloc-id:fake:payload
23480     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
23481     0x11/imm32/alloc-id:fake
23482     _string-copy/imm32/name
23483     0x11/imm32/alloc-id:fake
23484     Single-lit-var/imm32/inouts
23485     0x11/imm32/alloc-id:fake
23486     Single-int-var-in-ebx/imm32/outputs
23487     0x11/imm32/alloc-id:fake
23488     _string_bb_copy_to_ebx/imm32/subx-name
23489     0/imm32/no-rm32
23490     0/imm32/no-r32
23491     1/imm32/imm32-is-first-inout
23492     0/imm32/no-imm8
23493     0/imm32/no-disp32
23494     0/imm32/no-xm32
23495     0/imm32/no-x32
23496     0x11/imm32/alloc-id:fake
23497     _Primitive-copy-to-esi/imm32/next
23498 _Primitive-copy-to-esi:  # (payload primitive)
23499     0x11/imm32/alloc-id:fake:payload
23500     # var/esi <- copy lit => be/copy-to-esi lit/imm32
23501     0x11/imm32/alloc-id:fake
23502     _string-copy/imm32/name
23503     0x11/imm32/alloc-id:fake
23504     Single-lit-var/imm32/inouts
23505     0x11/imm32/alloc-id:fake
23506     Single-int-var-in-esi/imm32/outputs
23507     0x11/imm32/alloc-id:fake
23508     _string_be_copy_to_esi/imm32/subx-name
23509     0/imm32/no-rm32
23510     0/imm32/no-r32
23511     1/imm32/imm32-is-first-inout
23512     0/imm32/no-imm8
23513     0/imm32/no-disp32
23514     0/imm32/no-xm32
23515     0/imm32/no-x32
23516     0x11/imm32/alloc-id:fake
23517     _Primitive-copy-to-edi/imm32/next
23518 _Primitive-copy-to-edi:  # (payload primitive)
23519     0x11/imm32/alloc-id:fake:payload
23520     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
23521     0x11/imm32/alloc-id:fake
23522     _string-copy/imm32/name
23523     0x11/imm32/alloc-id:fake
23524     Single-lit-var/imm32/inouts
23525     0x11/imm32/alloc-id:fake
23526     Single-int-var-in-edi/imm32/outputs
23527     0x11/imm32/alloc-id:fake
23528     _string_bf_copy_to_edi/imm32/subx-name
23529     0/imm32/no-rm32
23530     0/imm32/no-r32
23531     1/imm32/imm32-is-first-inout
23532     0/imm32/no-imm8
23533     0/imm32/no-disp32
23534     0/imm32/no-xm32
23535     0/imm32/no-x32
23536     0x11/imm32/alloc-id:fake
23537     _Primitive-copy-reg-to-reg/imm32/next
23538 _Primitive-copy-reg-to-reg:  # (payload primitive)
23539     0x11/imm32/alloc-id:fake:payload
23540     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
23541     0x11/imm32/alloc-id:fake
23542     _string-copy/imm32/name
23543     0x11/imm32/alloc-id:fake
23544     Single-int-var-in-some-register/imm32/inouts
23545     0x11/imm32/alloc-id:fake
23546     Single-int-var-in-some-register/imm32/outputs
23547     0x11/imm32/alloc-id:fake
23548     _string_89_<-/imm32/subx-name
23549     3/imm32/rm32-is-first-output
23550     1/imm32/r32-is-first-inout
23551     0/imm32/no-imm32
23552     0/imm32/no-imm8
23553     0/imm32/no-disp32
23554     0/imm32/no-xm32
23555     0/imm32/no-x32
23556     0x11/imm32/alloc-id:fake
23557     _Primitive-copy-reg-to-mem/imm32/next
23558 _Primitive-copy-reg-to-mem:  # (payload primitive)
23559     0x11/imm32/alloc-id:fake:payload
23560     # copy-to var1 var2/reg => 89/<- var1 var2/r32
23561     0x11/imm32/alloc-id:fake
23562     _string-copy-to/imm32/name
23563     0x11/imm32/alloc-id:fake
23564     Two-args-int-stack-int-reg/imm32/inouts
23565     0/imm32/no-outputs
23566     0/imm32/no-outputs
23567     0x11/imm32/alloc-id:fake
23568     _string_89_<-/imm32/subx-name
23569     1/imm32/rm32-is-first-inout
23570     2/imm32/r32-is-second-inout
23571     0/imm32/no-imm32
23572     0/imm32/no-imm8
23573     0/imm32/no-disp32
23574     0/imm32/no-xm32
23575     0/imm32/no-x32
23576     0x11/imm32/alloc-id:fake
23577     _Primitive-copy-mem-to-reg/imm32/next
23578 _Primitive-copy-mem-to-reg:  # (payload primitive)
23579     0x11/imm32/alloc-id:fake:payload
23580     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
23581     0x11/imm32/alloc-id:fake
23582     _string-copy/imm32/name
23583     0x11/imm32/alloc-id:fake
23584     Single-int-var-in-mem/imm32/inouts
23585     0x11/imm32/alloc-id:fake
23586     Single-int-var-in-some-register/imm32/outputs
23587     0x11/imm32/alloc-id:fake
23588     _string_8b_->/imm32/subx-name
23589     1/imm32/rm32-is-first-inout
23590     3/imm32/r32-is-first-output
23591     0/imm32/no-imm32
23592     0/imm32/no-imm8
23593     0/imm32/no-disp32
23594     0/imm32/no-xm32
23595     0/imm32/no-x32
23596     0x11/imm32/alloc-id:fake
23597     _Primitive-copy-lit-to-reg/imm32/next
23598 _Primitive-copy-lit-to-reg:  # (payload primitive)
23599     0x11/imm32/alloc-id:fake:payload
23600     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
23601     0x11/imm32/alloc-id:fake
23602     _string-copy/imm32/name
23603     0x11/imm32/alloc-id:fake
23604     Single-lit-var/imm32/inouts
23605     0x11/imm32/alloc-id:fake
23606     Single-int-var-in-some-register/imm32/outputs
23607     0x11/imm32/alloc-id:fake
23608     _string_c7_subop_copy/imm32/subx-name
23609     3/imm32/rm32-is-first-output
23610     0/imm32/no-r32
23611     1/imm32/imm32-is-first-inout
23612     0/imm32/no-imm8
23613     0/imm32/no-disp32
23614     0/imm32/no-xm32
23615     0/imm32/no-x32
23616     0x11/imm32/alloc-id:fake
23617     _Primitive-copy-lit-to-mem/imm32/next
23618 _Primitive-copy-lit-to-mem:  # (payload primitive)
23619     0x11/imm32/alloc-id:fake:payload
23620     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
23621     0x11/imm32/alloc-id:fake
23622     _string-copy-to/imm32/name
23623     0x11/imm32/alloc-id:fake
23624     Int-var-and-literal/imm32/inouts
23625     0/imm32/no-outputs
23626     0/imm32/no-outputs
23627     0x11/imm32/alloc-id:fake
23628     _string_c7_subop_copy/imm32/subx-name
23629     1/imm32/rm32-is-first-inout
23630     0/imm32/no-r32
23631     2/imm32/imm32-is-second-inout
23632     0/imm32/no-imm8
23633     0/imm32/no-disp32
23634     0/imm32/no-xm32
23635     0/imm32/no-x32
23636     0x11/imm32/alloc-id:fake
23637     _Primitive-copy-byte-from-reg/imm32/next
23638 # - copy byte
23639 _Primitive-copy-byte-from-reg:
23640     0x11/imm32/alloc-id:fake:payload
23641     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
23642     0x11/imm32/alloc-id:fake
23643     _string-copy-byte/imm32/name
23644     0x11/imm32/alloc-id:fake
23645     Single-byte-var-in-some-register/imm32/inouts
23646     0x11/imm32/alloc-id:fake
23647     Single-byte-var-in-some-register/imm32/outputs
23648     0x11/imm32/alloc-id:fake
23649     _string_8a_copy_byte/imm32/subx-name
23650     1/imm32/rm32-is-first-inout
23651     3/imm32/r32-is-first-output
23652     0/imm32/no-imm32
23653     0/imm32/no-imm8
23654     0/imm32/no-disp32
23655     0/imm32/no-xm32
23656     0/imm32/no-x32
23657     0x11/imm32/alloc-id:fake
23658     _Primitive-copy-byte-from-mem/imm32/next
23659 _Primitive-copy-byte-from-mem:
23660     0x11/imm32/alloc-id:fake:payload
23661     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
23662     0x11/imm32/alloc-id:fake
23663     _string-copy-byte/imm32/name
23664     0x11/imm32/alloc-id:fake
23665     Single-byte-var-in-mem/imm32/inouts
23666     0x11/imm32/alloc-id:fake
23667     Single-byte-var-in-some-register/imm32/outputs
23668     0x11/imm32/alloc-id:fake
23669     _string_8a_copy_byte/imm32/subx-name
23670     1/imm32/rm32-is-first-inout
23671     3/imm32/r32-is-first-output
23672     0/imm32/no-imm32
23673     0/imm32/no-imm8
23674     0/imm32/no-disp32
23675     0/imm32/no-xm32
23676     0/imm32/no-x32
23677     0x11/imm32/alloc-id:fake
23678     _Primitive-copy-byte-to-mem/imm32/next
23679 _Primitive-copy-byte-to-mem:
23680     0x11/imm32/alloc-id:fake:payload
23681     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
23682     0x11/imm32/alloc-id:fake
23683     _string-copy-byte-to/imm32/name
23684     0x11/imm32/alloc-id:fake
23685     Two-args-byte-stack-byte-reg/imm32/inouts
23686     0/imm32/no-outputs
23687     0/imm32/no-outputs
23688     0x11/imm32/alloc-id:fake
23689     _string_88_copy_byte/imm32/subx-name
23690     1/imm32/rm32-is-first-inout
23691     2/imm32/r32-is-second-inout
23692     0/imm32/no-imm32
23693     0/imm32/no-imm8
23694     0/imm32/no-disp32
23695     0/imm32/no-xm32
23696     0/imm32/no-x32
23697     0x11/imm32/alloc-id:fake
23698     _Primitive-address/imm32/next
23699 # - address
23700 _Primitive-address:  # (payload primitive)
23701     0x11/imm32/alloc-id:fake:payload
23702     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
23703     0x11/imm32/alloc-id:fake
23704     _string-address/imm32/name
23705     0x11/imm32/alloc-id:fake
23706     Single-int-var-in-mem/imm32/inouts
23707     0x11/imm32/alloc-id:fake
23708     Single-addr-var-in-some-register/imm32/outputs
23709     0x11/imm32/alloc-id:fake
23710     _string_8d_copy_address/imm32/subx-name
23711     1/imm32/rm32-is-first-inout
23712     3/imm32/r32-is-first-output
23713     0/imm32/no-imm32
23714     0/imm32/no-imm8
23715     0/imm32/no-disp32
23716     0/imm32/no-xm32
23717     0/imm32/no-x32
23718     0x11/imm32/alloc-id:fake
23719     _Primitive-compare-reg-with-reg/imm32/next
23720 # - compare
23721 _Primitive-compare-reg-with-reg:  # (payload primitive)
23722     0x11/imm32/alloc-id:fake:payload
23723     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
23724     0x11/imm32/alloc-id:fake
23725     _string-compare/imm32/name
23726     0x11/imm32/alloc-id:fake
23727     Two-int-args-in-regs/imm32/inouts
23728     0/imm32/no-outputs
23729     0/imm32/no-outputs
23730     0x11/imm32/alloc-id:fake
23731     _string_39_compare->/imm32/subx-name
23732     1/imm32/rm32-is-first-inout
23733     2/imm32/r32-is-second-inout
23734     0/imm32/no-imm32
23735     0/imm32/no-imm8
23736     0/imm32/no-disp32
23737     0/imm32/no-xm32
23738     0/imm32/no-x32
23739     0x11/imm32/alloc-id:fake
23740     _Primitive-compare-mem-with-reg/imm32/next
23741 _Primitive-compare-mem-with-reg:  # (payload primitive)
23742     0x11/imm32/alloc-id:fake:payload
23743     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
23744     0x11/imm32/alloc-id:fake
23745     _string-compare/imm32/name
23746     0x11/imm32/alloc-id:fake
23747     Two-args-int-stack-int-reg/imm32/inouts
23748     0/imm32/no-outputs
23749     0/imm32/no-outputs
23750     0x11/imm32/alloc-id:fake
23751     _string_39_compare->/imm32/subx-name
23752     1/imm32/rm32-is-first-inout
23753     2/imm32/r32-is-second-inout
23754     0/imm32/no-imm32
23755     0/imm32/no-imm8
23756     0/imm32/no-disp32
23757     0/imm32/no-xm32
23758     0/imm32/no-x32
23759     0x11/imm32/alloc-id:fake
23760     _Primitive-compare-reg-with-mem/imm32/next
23761 _Primitive-compare-reg-with-mem:  # (payload primitive)
23762     0x11/imm32/alloc-id:fake:payload
23763     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
23764     0x11/imm32/alloc-id:fake
23765     _string-compare/imm32/name
23766     0x11/imm32/alloc-id:fake
23767     Two-args-int-reg-int-stack/imm32/inouts
23768     0/imm32/no-outputs
23769     0/imm32/no-outputs
23770     0x11/imm32/alloc-id:fake
23771     _string_3b_compare<-/imm32/subx-name
23772     2/imm32/rm32-is-second-inout
23773     1/imm32/r32-is-first-inout
23774     0/imm32/no-imm32
23775     0/imm32/no-imm8
23776     0/imm32/no-disp32
23777     0/imm32/no-xm32
23778     0/imm32/no-x32
23779     0x11/imm32/alloc-id:fake
23780     _Primitive-compare-eax-with-literal/imm32/next
23781 _Primitive-compare-eax-with-literal:  # (payload primitive)
23782     0x11/imm32/alloc-id:fake:payload
23783     # compare var1/eax n => 3d/compare-eax-with n/imm32
23784     0x11/imm32/alloc-id:fake
23785     _string-compare/imm32/name
23786     0x11/imm32/alloc-id:fake
23787     Two-args-int-eax-int-literal/imm32/inouts
23788     0/imm32/no-outputs
23789     0/imm32/no-outputs
23790     0x11/imm32/alloc-id:fake
23791     _string_3d_compare_eax_with/imm32/subx-name
23792     0/imm32/no-rm32
23793     0/imm32/no-r32
23794     2/imm32/imm32-is-second-inout
23795     0/imm32/no-imm8
23796     0/imm32/no-disp32
23797     0/imm32/no-xm32
23798     0/imm32/no-x32
23799     0x11/imm32/alloc-id:fake
23800     _Primitive-compare-reg-with-literal/imm32/next
23801 _Primitive-compare-reg-with-literal:  # (payload primitive)
23802     0x11/imm32/alloc-id:fake:payload
23803     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
23804     0x11/imm32/alloc-id:fake
23805     _string-compare/imm32/name
23806     0x11/imm32/alloc-id:fake
23807     Int-var-in-register-and-literal/imm32/inouts
23808     0/imm32/no-outputs
23809     0/imm32/no-outputs
23810     0x11/imm32/alloc-id:fake
23811     _string_81_subop_compare/imm32/subx-name
23812     1/imm32/rm32-is-first-inout
23813     0/imm32/no-r32
23814     2/imm32/imm32-is-second-inout
23815     0/imm32/no-imm8
23816     0/imm32/no-disp32
23817     0/imm32/no-xm32
23818     0/imm32/no-x32
23819     0x11/imm32/alloc-id:fake
23820     _Primitive-compare-mem-with-literal/imm32/next
23821 _Primitive-compare-mem-with-literal:  # (payload primitive)
23822     0x11/imm32/alloc-id:fake:payload
23823     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
23824     0x11/imm32/alloc-id:fake
23825     _string-compare/imm32/name
23826     0x11/imm32/alloc-id:fake
23827     Int-var-and-literal/imm32/inouts
23828     0/imm32/no-outputs
23829     0/imm32/no-outputs
23830     0x11/imm32/alloc-id:fake
23831     _string_81_subop_compare/imm32/subx-name
23832     1/imm32/rm32-is-first-inout
23833     0/imm32/no-r32
23834     2/imm32/imm32-is-second-inout
23835     0/imm32/no-imm8
23836     0/imm32/no-disp32
23837     0/imm32/no-xm32
23838     0/imm32/no-x32
23839     0x11/imm32/alloc-id:fake
23840     _Primitive-negate-reg/imm32/next
23841 # - negate
23842 _Primitive-negate-reg:  # (payload primitive)
23843     0x11/imm32/alloc-id:fake:payload
23844     # var1/reg <- negate => f7 3/subop/negate var1/rm32
23845     0x11/imm32/alloc-id:fake
23846     _string-negate/imm32/name
23847     0/imm32/no-inouts
23848     0/imm32/no-inouts
23849     0x11/imm32/alloc-id:fake
23850     Single-int-var-in-some-register/imm32/outputs
23851     0x11/imm32/alloc-id:fake
23852     _string_f7_subop_negate/imm32/subx-name
23853     3/imm32/rm32-is-first-output
23854     0/imm32/no-r32
23855     0/imm32/no-imm32
23856     0/imm32/no-imm8
23857     0/imm32/no-disp32
23858     0/imm32/no-xm32
23859     0/imm32/no-x32
23860     0x11/imm32/alloc-id:fake
23861     _Primitive-negate-mem/imm32/next
23862 _Primitive-negate-mem:  # (payload primitive)
23863     0x11/imm32/alloc-id:fake:payload
23864     # negate var1 => f7 3/subop/negate var1/rm32
23865     0x11/imm32/alloc-id:fake
23866     _string-negate/imm32/name
23867     0x11/imm32/alloc-id:fake
23868     Single-int-var-in-mem/imm32/inouts
23869     0/imm32/no-outputs
23870     0/imm32/no-outputs
23871     0x11/imm32/alloc-id:fake
23872     _string_f7_subop_negate/imm32/subx-name
23873     1/imm32/rm32-is-first-inout
23874     0/imm32/no-r32
23875     0/imm32/no-imm32
23876     0/imm32/no-imm8
23877     0/imm32/no-disp32
23878     0/imm32/no-xm32
23879     0/imm32/no-x32
23880     0x11/imm32/alloc-id:fake
23881     _Primitive-multiply-reg-by-reg/imm32/next
23882 # - multiply
23883 _Primitive-multiply-reg-by-reg:  # (payload primitive)
23884     0x11/imm32/alloc-id:fake:payload
23885     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
23886     0x11/imm32/alloc-id:fake
23887     _string-multiply/imm32/name
23888     0x11/imm32/alloc-id:fake
23889     Single-int-var-in-some-register/imm32/inouts
23890     0x11/imm32/alloc-id:fake
23891     Single-int-var-in-some-register/imm32/outputs
23892     0x11/imm32/alloc-id:fake
23893     _string_0f_af_multiply/imm32/subx-name
23894     1/imm32/rm32-is-first-inout
23895     3/imm32/r32-is-first-output
23896     0/imm32/no-imm32
23897     0/imm32/no-imm8
23898     0/imm32/no-disp32
23899     0/imm32/no-xm32
23900     0/imm32/no-x32
23901     0x11/imm32/alloc-id:fake
23902     _Primitive-multiply-reg-by-mem/imm32/next
23903 _Primitive-multiply-reg-by-mem:  # (payload primitive)
23904     0x11/imm32/alloc-id:fake:payload
23905     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
23906     0x11/imm32/alloc-id:fake
23907     _string-multiply/imm32/name
23908     0x11/imm32/alloc-id:fake
23909     Single-int-var-in-mem/imm32/inouts
23910     0x11/imm32/alloc-id:fake
23911     Single-int-var-in-some-register/imm32/outputs
23912     0x11/imm32/alloc-id:fake
23913     _string_0f_af_multiply/imm32/subx-name
23914     1/imm32/rm32-is-first-inout
23915     3/imm32/r32-is-first-output
23916     0/imm32/no-imm32
23917     0/imm32/no-imm8
23918     0/imm32/no-disp32
23919     0/imm32/no-xm32
23920     0/imm32/no-x32
23921     0x11/imm32/alloc-id:fake
23922     _Primitive-convert-mem-to-xreg/imm32/next
23923 # - convert int to floating point
23924 _Primitive-convert-mem-to-xreg:  # (payload primitive)
23925     0x11/imm32/alloc-id:fake:payload
23926     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
23927     0x11/imm32/alloc-id:fake
23928     _string-convert/imm32/name
23929     0x11/imm32/alloc-id:fake
23930     Single-int-var-in-mem/imm32/inouts
23931     0x11/imm32/alloc-id:fake
23932     Single-float-var-in-some-register/imm32/outputs
23933     0x11/imm32/alloc-id:fake
23934     _string_f3_0f_2a_convert_to_float/imm32/subx-name
23935     1/imm32/rm32-is-first-inout
23936     0/imm32/no-r32
23937     0/imm32/no-imm32
23938     0/imm32/no-imm8
23939     0/imm32/no-disp32
23940     0/imm32/no-xm32
23941     3/imm32/x32-is-first-output
23942     0x11/imm32/alloc-id:fake
23943     _Primitive-convert-reg-to-xreg/imm32/next
23944 _Primitive-convert-reg-to-xreg:  # (payload primitive)
23945     0x11/imm32/alloc-id:fake:payload
23946     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
23947     0x11/imm32/alloc-id:fake
23948     _string-convert/imm32/name
23949     0x11/imm32/alloc-id:fake
23950     Single-int-var-in-some-register/imm32/inouts
23951     0x11/imm32/alloc-id:fake
23952     Single-float-var-in-some-register/imm32/outputs
23953     0x11/imm32/alloc-id:fake
23954     _string_f3_0f_2a_convert_to_float/imm32/subx-name
23955     1/imm32/rm32-is-first-inout
23956     0/imm32/no-r32
23957     0/imm32/no-imm32
23958     0/imm32/no-imm8
23959     0/imm32/no-disp32
23960     0/imm32/no-xm32
23961     3/imm32/x32-is-first-output
23962     0x11/imm32/alloc-id:fake
23963     _Primitive-convert-xmem-to-reg/imm32/next
23964 # - convert floating point to int
23965 _Primitive-convert-xmem-to-reg:  # (payload primitive)
23966     0x11/imm32/alloc-id:fake:payload
23967     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
23968     0x11/imm32/alloc-id:fake
23969     _string-convert/imm32/name
23970     0x11/imm32/alloc-id:fake
23971     Single-float-var-in-mem/imm32/inouts
23972     0x11/imm32/alloc-id:fake
23973     Single-int-var-in-some-register/imm32/outputs
23974     0x11/imm32/alloc-id:fake
23975     _string_f3_0f_2d_convert_to_int/imm32/subx-name
23976     0/imm32/no-rm32
23977     3/imm32/r32-is-first-output
23978     0/imm32/no-imm32
23979     0/imm32/no-imm8
23980     0/imm32/no-disp32
23981     1/imm32/xm32-is-first-inout
23982     0/imm32/no-x32
23983     0x11/imm32/alloc-id:fake
23984     _Primitive-convert-xreg-to-reg/imm32/next
23985 _Primitive-convert-xreg-to-reg:  # (payload primitive)
23986     0x11/imm32/alloc-id:fake:payload
23987     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
23988     0x11/imm32/alloc-id:fake
23989     _string-convert/imm32/name
23990     0x11/imm32/alloc-id:fake
23991     Single-float-var-in-some-register/imm32/inouts
23992     0x11/imm32/alloc-id:fake
23993     Single-int-var-in-some-register/imm32/outputs
23994     0x11/imm32/alloc-id:fake
23995     _string_f3_0f_2d_convert_to_int/imm32/subx-name
23996     0/imm32/no-rm32
23997     3/imm32/r32-is-first-output
23998     0/imm32/no-imm32
23999     0/imm32/no-imm8
24000     0/imm32/no-disp32
24001     1/imm32/xm32-is-first-inout
24002     0/imm32/no-x32
24003     0x11/imm32/alloc-id:fake
24004     _Primitive-truncate-xmem-to-reg/imm32/next
24005 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
24006     0x11/imm32/alloc-id:fake:payload
24007     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
24008     0x11/imm32/alloc-id:fake
24009     _string-truncate/imm32/name
24010     0x11/imm32/alloc-id:fake
24011     Single-float-var-in-mem/imm32/inouts
24012     0x11/imm32/alloc-id:fake
24013     Single-int-var-in-some-register/imm32/outputs
24014     0x11/imm32/alloc-id:fake
24015     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
24016     0/imm32/no-rm32
24017     3/imm32/r32-is-first-output
24018     0/imm32/no-imm32
24019     0/imm32/no-imm8
24020     0/imm32/no-disp32
24021     1/imm32/xm32-is-first-inout
24022     0/imm32/no-x32
24023     0x11/imm32/alloc-id:fake
24024     _Primitive-truncate-xreg-to-reg/imm32/next
24025 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
24026     0x11/imm32/alloc-id:fake:payload
24027     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
24028     0x11/imm32/alloc-id:fake
24029     _string-truncate/imm32/name
24030     0x11/imm32/alloc-id:fake
24031     Single-float-var-in-some-register/imm32/inouts
24032     0x11/imm32/alloc-id:fake
24033     Single-int-var-in-some-register/imm32/outputs
24034     0x11/imm32/alloc-id:fake
24035     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
24036     0/imm32/no-rm32
24037     3/imm32/r32-is-first-output
24038     0/imm32/no-imm32
24039     0/imm32/no-imm8
24040     0/imm32/no-disp32
24041     1/imm32/xm32-is-first-inout
24042     0/imm32/no-x32
24043     0x11/imm32/alloc-id:fake
24044     _Primitive-reinterpret-xmem-as-reg/imm32/next
24045 # - reinterpret bytes (just for debugging)
24046 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
24047     0x11/imm32/alloc-id:fake:payload
24048     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
24049     0x11/imm32/alloc-id:fake
24050     _string-reinterpret/imm32/name
24051     0x11/imm32/alloc-id:fake
24052     Single-float-var-in-mem/imm32/inouts
24053     0x11/imm32/alloc-id:fake
24054     Single-int-var-in-some-register/imm32/outputs
24055     0x11/imm32/alloc-id:fake
24056     _string_8b_->/imm32/subx-name
24057     0/imm32/no-rm32
24058     3/imm32/r32-is-first-output
24059     0/imm32/no-imm32
24060     0/imm32/no-imm8
24061     0/imm32/no-disp32
24062     1/imm32/xm32-is-first-inout
24063     0/imm32/no-x32
24064     0x11/imm32/alloc-id:fake
24065     _Primitive-reinterpret-mem-as-xreg/imm32/next
24066 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
24067     0x11/imm32/alloc-id:fake:payload
24068     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
24069     0x11/imm32/alloc-id:fake
24070     _string-reinterpret/imm32/name
24071     0x11/imm32/alloc-id:fake
24072     Single-int-var-in-mem/imm32/inouts
24073     0x11/imm32/alloc-id:fake
24074     Single-float-var-in-some-register/imm32/outputs
24075     0x11/imm32/alloc-id:fake
24076     _string_f3_0f_10_copy/imm32/subx-name
24077     1/imm32/rm32-is-first-inout
24078     0/imm32/no-r32
24079     0/imm32/no-imm32
24080     0/imm32/no-imm8
24081     0/imm32/no-disp32
24082     0/imm32/no-xm32
24083     3/imm32/x32-is-first-output
24084     0x11/imm32/alloc-id:fake
24085     _Primitive-copy-xreg-to-xreg/imm32/next
24086 # - floating-point copy
24087 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
24088     0x11/imm32/alloc-id:fake:payload
24089     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
24090     0x11/imm32/alloc-id:fake
24091     _string-copy/imm32/name
24092     0x11/imm32/alloc-id:fake
24093     Single-float-var-in-some-register/imm32/inouts
24094     0x11/imm32/alloc-id:fake
24095     Single-float-var-in-some-register/imm32/outputs
24096     0x11/imm32/alloc-id:fake
24097     _string_f3_0f_11_copy/imm32/subx-name
24098     0/imm32/no-rm32
24099     0/imm32/no-r32
24100     0/imm32/no-imm32
24101     0/imm32/no-imm8
24102     0/imm32/no-disp32
24103     3/imm32/xm32-is-first-output
24104     1/imm32/x32-is-first-inout
24105     0x11/imm32/alloc-id:fake
24106     _Primitive-copy-xreg-to-mem/imm32/next
24107 _Primitive-copy-xreg-to-mem:  # (payload primitive)
24108     0x11/imm32/alloc-id:fake:payload
24109     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
24110     0x11/imm32/alloc-id:fake
24111     _string-copy-to/imm32/name
24112     0x11/imm32/alloc-id:fake
24113     Two-args-float-stack-float-reg/imm32/inouts
24114     0/imm32/no-outputs
24115     0/imm32/no-outputs
24116     0x11/imm32/alloc-id:fake
24117     _string_f3_0f_11_copy/imm32/subx-name
24118     0/imm32/no-rm32
24119     0/imm32/no-r32
24120     0/imm32/no-imm32
24121     0/imm32/no-imm8
24122     0/imm32/no-disp32
24123     1/imm32/xm32-is-first-inout
24124     2/imm32/x32-is-second-inout
24125     0x11/imm32/alloc-id:fake
24126     _Primitive-copy-mem-to-xreg/imm32/next
24127 _Primitive-copy-mem-to-xreg:  # (payload primitive)
24128     0x11/imm32/alloc-id:fake:payload
24129     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
24130     0x11/imm32/alloc-id:fake
24131     _string-copy/imm32/name
24132     0x11/imm32/alloc-id:fake
24133     Single-float-var-in-mem/imm32/inouts
24134     0x11/imm32/alloc-id:fake
24135     Single-float-var-in-some-register/imm32/outputs
24136     0x11/imm32/alloc-id:fake
24137     _string_f3_0f_10_copy/imm32/subx-name
24138     0/imm32/no-rm32
24139     0/imm32/no-r32
24140     0/imm32/no-imm32
24141     0/imm32/no-imm8
24142     0/imm32/no-disp32
24143     1/imm32/xm32-is-first-inout
24144     3/imm32/x32-is-first-output
24145     0x11/imm32/alloc-id:fake
24146     _Primitive-address-of-xmem/imm32/next
24147 # - floating-point-address
24148 _Primitive-address-of-xmem:  # (payload primitive)
24149     0x11/imm32/alloc-id:fake:payload
24150     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
24151     0x11/imm32/alloc-id:fake
24152     _string-address/imm32/name
24153     0x11/imm32/alloc-id:fake
24154     Single-float-var-in-mem/imm32/inouts
24155     0x11/imm32/alloc-id:fake
24156     Single-addr-var-in-some-register/imm32/outputs
24157     0x11/imm32/alloc-id:fake
24158     _string_8d_copy_address/imm32/subx-name
24159     1/imm32/rm32-is-first-inout
24160     3/imm32/r32-is-first-output
24161     0/imm32/no-imm32
24162     0/imm32/no-imm8
24163     0/imm32/no-disp32
24164     0/imm32/no-xm32
24165     0/imm32/no-x32
24166     0x11/imm32/alloc-id:fake
24167     _Primitive-add-xreg-to-xreg/imm32/next
24168 # - floating-point add
24169 _Primitive-add-xreg-to-xreg:  # (payload primitive)
24170     0x11/imm32/alloc-id:fake:payload
24171     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
24172     0x11/imm32/alloc-id:fake
24173     _string-add/imm32/name
24174     0x11/imm32/alloc-id:fake
24175     Single-float-var-in-some-register/imm32/inouts
24176     0x11/imm32/alloc-id:fake
24177     Single-float-var-in-some-register/imm32/outputs
24178     0x11/imm32/alloc-id:fake
24179     _string_f3_0f_58_add/imm32/subx-name
24180     0/imm32/no-rm32
24181     0/imm32/no-r32
24182     0/imm32/no-imm32
24183     0/imm32/no-imm8
24184     0/imm32/no-disp32
24185     1/imm32/xm32-is-first-inout
24186     3/imm32/x32-is-first-output
24187     0x11/imm32/alloc-id:fake
24188     _Primitive-add-mem-to-xreg/imm32/next
24189 _Primitive-add-mem-to-xreg:  # (payload primitive)
24190     0x11/imm32/alloc-id:fake:payload
24191     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
24192     0x11/imm32/alloc-id:fake
24193     _string-add/imm32/name
24194     0x11/imm32/alloc-id:fake
24195     Single-float-var-in-mem/imm32/inouts
24196     0x11/imm32/alloc-id:fake
24197     Single-float-var-in-some-register/imm32/outputs
24198     0x11/imm32/alloc-id:fake
24199     _string_f3_0f_58_add/imm32/subx-name
24200     0/imm32/no-rm32
24201     0/imm32/no-r32
24202     0/imm32/no-imm32
24203     0/imm32/no-imm8
24204     0/imm32/no-disp32
24205     1/imm32/xm32-is-first-inout
24206     3/imm32/x32-is-first-output
24207     0x11/imm32/alloc-id:fake
24208     _Primitive-subtract-xreg-from-xreg/imm32/next
24209 # - floating-point subtract
24210 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
24211     0x11/imm32/alloc-id:fake:payload
24212     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
24213     0x11/imm32/alloc-id:fake
24214     _string-subtract/imm32/name
24215     0x11/imm32/alloc-id:fake
24216     Single-float-var-in-some-register/imm32/inouts
24217     0x11/imm32/alloc-id:fake
24218     Single-float-var-in-some-register/imm32/outputs
24219     0x11/imm32/alloc-id:fake
24220     _string_f3_0f_5c_subtract/imm32/subx-name
24221     0/imm32/no-rm32
24222     0/imm32/no-r32
24223     0/imm32/no-imm32
24224     0/imm32/no-imm8
24225     0/imm32/no-disp32
24226     1/imm32/xm32-is-first-inout
24227     3/imm32/x32-is-first-output
24228     0x11/imm32/alloc-id:fake
24229     _Primitive-subtract-mem-from-xreg/imm32/next
24230 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
24231     0x11/imm32/alloc-id:fake:payload
24232     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
24233     0x11/imm32/alloc-id:fake
24234     _string-subtract/imm32/name
24235     0x11/imm32/alloc-id:fake
24236     Single-float-var-in-mem/imm32/inouts
24237     0x11/imm32/alloc-id:fake
24238     Single-float-var-in-some-register/imm32/outputs
24239     0x11/imm32/alloc-id:fake
24240     _string_f3_0f_5c_subtract/imm32/subx-name
24241     0/imm32/no-rm32
24242     0/imm32/no-r32
24243     0/imm32/no-imm32
24244     0/imm32/no-imm8
24245     0/imm32/no-disp32
24246     1/imm32/xm32-is-first-inout
24247     3/imm32/x32-is-first-output
24248     0x11/imm32/alloc-id:fake
24249     _Primitive-multiply-xreg-by-xreg/imm32/next
24250 # - floating-point multiply
24251 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
24252     0x11/imm32/alloc-id:fake:payload
24253     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
24254     0x11/imm32/alloc-id:fake
24255     _string-multiply/imm32/name
24256     0x11/imm32/alloc-id:fake
24257     Single-float-var-in-some-register/imm32/inouts
24258     0x11/imm32/alloc-id:fake
24259     Single-float-var-in-some-register/imm32/outputs
24260     0x11/imm32/alloc-id:fake
24261     _string_f3_0f_59_multiply/imm32/subx-name
24262     0/imm32/no-rm32
24263     0/imm32/no-r32
24264     0/imm32/no-imm32
24265     0/imm32/no-imm8
24266     0/imm32/no-disp32
24267     1/imm32/xm32-is-first-inout
24268     3/imm32/x32-is-first-output
24269     0x11/imm32/alloc-id:fake
24270     _Primitive-multiply-xreg-by-mem/imm32/next
24271 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
24272     0x11/imm32/alloc-id:fake:payload
24273     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
24274     0x11/imm32/alloc-id:fake
24275     _string-multiply/imm32/name
24276     0x11/imm32/alloc-id:fake
24277     Single-float-var-in-mem/imm32/inouts
24278     0x11/imm32/alloc-id:fake
24279     Single-float-var-in-some-register/imm32/outputs
24280     0x11/imm32/alloc-id:fake
24281     _string_f3_0f_59_multiply/imm32/subx-name
24282     0/imm32/no-rm32
24283     0/imm32/no-r32
24284     0/imm32/no-imm32
24285     0/imm32/no-imm8
24286     0/imm32/no-disp32
24287     1/imm32/xm32-is-first-inout
24288     3/imm32/x32-is-first-output
24289     0x11/imm32/alloc-id:fake
24290     _Primitive-divide-xreg-by-xreg/imm32/next
24291 # - floating-point divide
24292 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
24293     0x11/imm32/alloc-id:fake:payload
24294     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
24295     0x11/imm32/alloc-id:fake
24296     _string-divide/imm32/name
24297     0x11/imm32/alloc-id:fake
24298     Single-float-var-in-some-register/imm32/inouts
24299     0x11/imm32/alloc-id:fake
24300     Single-float-var-in-some-register/imm32/outputs
24301     0x11/imm32/alloc-id:fake
24302     _string_f3_0f_5e_divide/imm32/subx-name
24303     0/imm32/no-rm32
24304     0/imm32/no-r32
24305     0/imm32/no-imm32
24306     0/imm32/no-imm8
24307     0/imm32/no-disp32
24308     1/imm32/xm32-is-first-inout
24309     3/imm32/x32-is-first-output
24310     0x11/imm32/alloc-id:fake
24311     _Primitive-divide-xreg-by-mem/imm32/next
24312 _Primitive-divide-xreg-by-mem:  # (payload primitive)
24313     0x11/imm32/alloc-id:fake:payload
24314     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
24315     0x11/imm32/alloc-id:fake
24316     _string-divide/imm32/name
24317     0x11/imm32/alloc-id:fake
24318     Single-float-var-in-mem/imm32/inouts
24319     0x11/imm32/alloc-id:fake
24320     Single-float-var-in-some-register/imm32/outputs
24321     0x11/imm32/alloc-id:fake
24322     _string_f3_0f_5e_divide/imm32/subx-name
24323     0/imm32/no-rm32
24324     0/imm32/no-r32
24325     0/imm32/no-imm32
24326     0/imm32/no-imm8
24327     0/imm32/no-disp32
24328     1/imm32/xm32-is-first-inout
24329     3/imm32/x32-is-first-output
24330     0x11/imm32/alloc-id:fake
24331     _Primitive-max-xreg-with-xreg/imm32/next
24332 # - floating-point maximum
24333 _Primitive-max-xreg-with-xreg:  # (payload primitive)
24334     0x11/imm32/alloc-id:fake:payload
24335     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
24336     0x11/imm32/alloc-id:fake
24337     _string-max/imm32/name
24338     0x11/imm32/alloc-id:fake
24339     Single-float-var-in-some-register/imm32/inouts
24340     0x11/imm32/alloc-id:fake
24341     Single-float-var-in-some-register/imm32/outputs
24342     0x11/imm32/alloc-id:fake
24343     _string_f3_0f_5f_max/imm32/subx-name
24344     0/imm32/no-rm32
24345     0/imm32/no-r32
24346     0/imm32/no-imm32
24347     0/imm32/no-imm8
24348     0/imm32/no-disp32
24349     1/imm32/xm32-is-first-inout
24350     3/imm32/x32-is-first-output
24351     0x11/imm32/alloc-id:fake
24352     _Primitive-max-xreg-with-mem/imm32/next
24353 _Primitive-max-xreg-with-mem:  # (payload primitive)
24354     0x11/imm32/alloc-id:fake:payload
24355     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
24356     0x11/imm32/alloc-id:fake
24357     _string-max/imm32/name
24358     0x11/imm32/alloc-id:fake
24359     Single-float-var-in-mem/imm32/inouts
24360     0x11/imm32/alloc-id:fake
24361     Single-float-var-in-some-register/imm32/outputs
24362     0x11/imm32/alloc-id:fake
24363     _string_f3_0f_5f_max/imm32/subx-name
24364     0/imm32/no-rm32
24365     0/imm32/no-r32
24366     0/imm32/no-imm32
24367     0/imm32/no-imm8
24368     0/imm32/no-disp32
24369     1/imm32/xm32-is-first-inout
24370     3/imm32/x32-is-first-output
24371     0x11/imm32/alloc-id:fake
24372     _Primitive-min-xreg-with-xreg/imm32/next
24373 # - floating-point minimum
24374 _Primitive-min-xreg-with-xreg:  # (payload primitive)
24375     0x11/imm32/alloc-id:fake:payload
24376     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
24377     0x11/imm32/alloc-id:fake
24378     _string-min/imm32/name
24379     0x11/imm32/alloc-id:fake
24380     Single-float-var-in-some-register/imm32/inouts
24381     0x11/imm32/alloc-id:fake
24382     Single-float-var-in-some-register/imm32/outputs
24383     0x11/imm32/alloc-id:fake
24384     _string_f3_0f_5d_min/imm32/subx-name
24385     0/imm32/no-rm32
24386     0/imm32/no-r32
24387     0/imm32/no-imm32
24388     0/imm32/no-imm8
24389     0/imm32/no-disp32
24390     1/imm32/xm32-is-first-inout
24391     3/imm32/x32-is-first-output
24392     0x11/imm32/alloc-id:fake
24393     _Primitive-min-xreg-with-mem/imm32/next
24394 _Primitive-min-xreg-with-mem:  # (payload primitive)
24395     0x11/imm32/alloc-id:fake:payload
24396     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
24397     0x11/imm32/alloc-id:fake
24398     _string-min/imm32/name
24399     0x11/imm32/alloc-id:fake
24400     Single-float-var-in-mem/imm32/inouts
24401     0x11/imm32/alloc-id:fake
24402     Single-float-var-in-some-register/imm32/outputs
24403     0x11/imm32/alloc-id:fake
24404     _string_f3_0f_5d_min/imm32/subx-name
24405     0/imm32/no-rm32
24406     0/imm32/no-r32
24407     0/imm32/no-imm32
24408     0/imm32/no-imm8
24409     0/imm32/no-disp32
24410     1/imm32/xm32-is-first-inout
24411     3/imm32/x32-is-first-output
24412     0x11/imm32/alloc-id:fake
24413     _Primitive-reciprocal-xreg-to-xreg/imm32/next
24414 # - floating-point reciprocal
24415 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
24416     0x11/imm32/alloc-id:fake:payload
24417     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
24418     0x11/imm32/alloc-id:fake
24419     _string-reciprocal/imm32/name
24420     0x11/imm32/alloc-id:fake
24421     Single-float-var-in-some-register/imm32/inouts
24422     0x11/imm32/alloc-id:fake
24423     Single-float-var-in-some-register/imm32/outputs
24424     0x11/imm32/alloc-id:fake
24425     _string_f3_0f_53_reciprocal/imm32/subx-name
24426     0/imm32/no-rm32
24427     0/imm32/no-r32
24428     0/imm32/no-imm32
24429     0/imm32/no-imm8
24430     0/imm32/no-disp32
24431     1/imm32/xm32-is-first-inout
24432     3/imm32/x32-is-first-output
24433     0x11/imm32/alloc-id:fake
24434     _Primitive-reciprocal-mem-to-xreg/imm32/next
24435 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
24436     0x11/imm32/alloc-id:fake:payload
24437     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
24438     0x11/imm32/alloc-id:fake
24439     _string-reciprocal/imm32/name
24440     0x11/imm32/alloc-id:fake
24441     Single-float-var-in-mem/imm32/inouts
24442     0x11/imm32/alloc-id:fake
24443     Single-float-var-in-some-register/imm32/outputs
24444     0x11/imm32/alloc-id:fake
24445     _string_f3_0f_53_reciprocal/imm32/subx-name
24446     0/imm32/no-rm32
24447     0/imm32/no-r32
24448     0/imm32/no-imm32
24449     0/imm32/no-imm8
24450     0/imm32/no-disp32
24451     1/imm32/xm32-is-first-inout
24452     3/imm32/x32-is-first-output
24453     0x11/imm32/alloc-id:fake
24454     _Primitive-square-root-xreg-to-xreg/imm32/next
24455 # - floating-point square root
24456 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
24457     0x11/imm32/alloc-id:fake:payload
24458     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
24459     0x11/imm32/alloc-id:fake
24460     _string-square-root/imm32/name
24461     0x11/imm32/alloc-id:fake
24462     Single-float-var-in-some-register/imm32/inouts
24463     0x11/imm32/alloc-id:fake
24464     Single-float-var-in-some-register/imm32/outputs
24465     0x11/imm32/alloc-id:fake
24466     _string_f3_0f_51_square_root/imm32/subx-name
24467     0/imm32/no-rm32
24468     0/imm32/no-r32
24469     0/imm32/no-imm32
24470     0/imm32/no-imm8
24471     0/imm32/no-disp32
24472     1/imm32/xm32-is-first-inout
24473     3/imm32/x32-is-first-output
24474     0x11/imm32/alloc-id:fake
24475     _Primitive-square-root-mem-to-xreg/imm32/next
24476 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
24477     0x11/imm32/alloc-id:fake:payload
24478     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
24479     0x11/imm32/alloc-id:fake
24480     _string-square-root/imm32/name
24481     0x11/imm32/alloc-id:fake
24482     Single-float-var-in-mem/imm32/inouts
24483     0x11/imm32/alloc-id:fake
24484     Single-float-var-in-some-register/imm32/outputs
24485     0x11/imm32/alloc-id:fake
24486     _string_f3_0f_51_square_root/imm32/subx-name
24487     0/imm32/no-rm32
24488     0/imm32/no-r32
24489     0/imm32/no-imm32
24490     0/imm32/no-imm8
24491     0/imm32/no-disp32
24492     1/imm32/xm32-is-first-inout
24493     3/imm32/x32-is-first-output
24494     0x11/imm32/alloc-id:fake
24495     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
24496 # - floating-point inverse square root 1/sqrt(x)
24497 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
24498     0x11/imm32/alloc-id:fake:payload
24499     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
24500     0x11/imm32/alloc-id:fake
24501     _string-inverse-square-root/imm32/name
24502     0x11/imm32/alloc-id:fake
24503     Single-float-var-in-some-register/imm32/inouts
24504     0x11/imm32/alloc-id:fake
24505     Single-float-var-in-some-register/imm32/outputs
24506     0x11/imm32/alloc-id:fake
24507     _string_f3_0f_52_inverse_square_root/imm32/subx-name
24508     0/imm32/no-rm32
24509     0/imm32/no-r32
24510     0/imm32/no-imm32
24511     0/imm32/no-imm8
24512     0/imm32/no-disp32
24513     1/imm32/xm32-is-first-inout
24514     3/imm32/x32-is-first-output
24515     0x11/imm32/alloc-id:fake
24516     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
24517 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
24518     0x11/imm32/alloc-id:fake:payload
24519     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
24520     0x11/imm32/alloc-id:fake
24521     _string-inverse-square-root/imm32/name
24522     0x11/imm32/alloc-id:fake
24523     Single-float-var-in-mem/imm32/inouts
24524     0x11/imm32/alloc-id:fake
24525     Single-float-var-in-some-register/imm32/outputs
24526     0x11/imm32/alloc-id:fake
24527     _string_f3_0f_52_inverse_square_root/imm32/subx-name
24528     0/imm32/no-rm32
24529     0/imm32/no-r32
24530     0/imm32/no-imm32
24531     0/imm32/no-imm8
24532     0/imm32/no-disp32
24533     1/imm32/xm32-is-first-inout
24534     3/imm32/x32-is-first-output
24535     0x11/imm32/alloc-id:fake
24536     _Primitive-compare-xreg-with-xreg/imm32/next
24537 # - floating-point compare
24538 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
24539     0x11/imm32/alloc-id:fake:payload
24540     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
24541     0x11/imm32/alloc-id:fake
24542     _string-compare/imm32/name
24543     0x11/imm32/alloc-id:fake
24544     Two-float-args-in-regs/imm32/inouts
24545     0/imm32/no-outputs
24546     0/imm32/no-outputs
24547     0x11/imm32/alloc-id:fake
24548     _string_0f_2f_compare/imm32/subx-name
24549     0/imm32/no-rm32
24550     0/imm32/no-r32
24551     0/imm32/no-imm32
24552     0/imm32/no-imm8
24553     0/imm32/no-disp32
24554     1/imm32/xm32-is-first-inout
24555     2/imm32/x32-is-second-inout
24556     0x11/imm32/alloc-id:fake
24557     _Primitive-compare-xreg-with-mem/imm32/next
24558 _Primitive-compare-xreg-with-mem:  # (payload primitive)
24559     0x11/imm32/alloc-id:fake:payload
24560     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
24561     0x11/imm32/alloc-id:fake
24562     _string-compare/imm32/name
24563     0x11/imm32/alloc-id:fake
24564     Two-args-float-reg-float-stack/imm32/inouts
24565     0/imm32/no-outputs
24566     0/imm32/no-outputs
24567     0x11/imm32/alloc-id:fake
24568     _string_0f_2f_compare/imm32/subx-name
24569     0/imm32/no-rm32
24570     0/imm32/no-r32
24571     0/imm32/no-imm32
24572     0/imm32/no-imm8
24573     0/imm32/no-disp32
24574     2/imm32/xm32-is-second-inout
24575     1/imm32/x32-is-first-inout
24576     0x11/imm32/alloc-id:fake
24577     _Primitive-break-if-addr</imm32/next
24578 # - branches
24579 _Primitive-break-if-addr<:  # (payload primitive)
24580     0x11/imm32/alloc-id:fake:payload
24581     0x11/imm32/alloc-id:fake
24582     _string-break-if-addr</imm32/name
24583     0/imm32/no-inouts
24584     0/imm32/no-inouts
24585     0/imm32/no-outputs
24586     0/imm32/no-outputs
24587     0x11/imm32/alloc-id:fake
24588     _string_0f_82_jump_break/imm32/subx-name
24589     0/imm32/no-rm32
24590     0/imm32/no-r32
24591     0/imm32/no-imm32
24592     0/imm32/no-imm8
24593     0/imm32/no-disp32
24594     0/imm32/no-xm32
24595     0/imm32/no-x32
24596     0x11/imm32/alloc-id:fake
24597     _Primitive-break-if-addr>=/imm32/next
24598 _Primitive-break-if-addr>=:  # (payload primitive)
24599     0x11/imm32/alloc-id:fake:payload
24600     0x11/imm32/alloc-id:fake
24601     _string-break-if-addr>=/imm32/name
24602     0/imm32/no-inouts
24603     0/imm32/no-inouts
24604     0/imm32/no-outputs
24605     0/imm32/no-outputs
24606     0x11/imm32/alloc-id:fake
24607     _string_0f_83_jump_break/imm32/subx-name
24608     0/imm32/no-rm32
24609     0/imm32/no-r32
24610     0/imm32/no-imm32
24611     0/imm32/no-imm8
24612     0/imm32/no-disp32
24613     0/imm32/no-xm32
24614     0/imm32/no-x32
24615     0x11/imm32/alloc-id:fake
24616     _Primitive-break-if-=/imm32/next
24617 _Primitive-break-if-=:  # (payload primitive)
24618     0x11/imm32/alloc-id:fake:payload
24619     0x11/imm32/alloc-id:fake
24620     _string-break-if-=/imm32/name
24621     0/imm32/no-inouts
24622     0/imm32/no-inouts
24623     0/imm32/no-outputs
24624     0/imm32/no-outputs
24625     0x11/imm32/alloc-id:fake
24626     _string_0f_84_jump_break/imm32/subx-name
24627     0/imm32/no-rm32
24628     0/imm32/no-r32
24629     0/imm32/no-imm32
24630     0/imm32/no-imm8
24631     0/imm32/no-disp32
24632     0/imm32/no-xm32
24633     0/imm32/no-x32
24634     0x11/imm32/alloc-id:fake
24635     _Primitive-break-if-!=/imm32/next
24636 _Primitive-break-if-!=:  # (payload primitive)
24637     0x11/imm32/alloc-id:fake:payload
24638     0x11/imm32/alloc-id:fake
24639     _string-break-if-!=/imm32/name
24640     0/imm32/no-inouts
24641     0/imm32/no-inouts
24642     0/imm32/no-outputs
24643     0/imm32/no-outputs
24644     0x11/imm32/alloc-id:fake
24645     _string_0f_85_jump_break/imm32/subx-name
24646     0/imm32/no-rm32
24647     0/imm32/no-r32
24648     0/imm32/no-imm32
24649     0/imm32/no-imm8
24650     0/imm32/no-disp32
24651     0/imm32/no-xm32
24652     0/imm32/no-x32
24653     0x11/imm32/alloc-id:fake
24654     _Primitive-break-if-addr<=/imm32/next
24655 _Primitive-break-if-addr<=:  # (payload primitive)
24656     0x11/imm32/alloc-id:fake:payload
24657     0x11/imm32/alloc-id:fake
24658     _string-break-if-addr<=/imm32/name
24659     0/imm32/no-inouts
24660     0/imm32/no-inouts
24661     0/imm32/no-outputs
24662     0/imm32/no-outputs
24663     0x11/imm32/alloc-id:fake
24664     _string_0f_86_jump_break/imm32/subx-name
24665     0/imm32/no-rm32
24666     0/imm32/no-r32
24667     0/imm32/no-imm32
24668     0/imm32/no-imm8
24669     0/imm32/no-disp32
24670     0/imm32/no-xm32
24671     0/imm32/no-x32
24672     0x11/imm32/alloc-id:fake
24673     _Primitive-break-if-addr>/imm32/next
24674 _Primitive-break-if-addr>:  # (payload primitive)
24675     0x11/imm32/alloc-id:fake:payload
24676     0x11/imm32/alloc-id:fake
24677     _string-break-if-addr>/imm32/name
24678     0/imm32/no-inouts
24679     0/imm32/no-inouts
24680     0/imm32/no-outputs
24681     0/imm32/no-outputs
24682     0x11/imm32/alloc-id:fake
24683     _string_0f_87_jump_break/imm32/subx-name
24684     0/imm32/no-rm32
24685     0/imm32/no-r32
24686     0/imm32/no-imm32
24687     0/imm32/no-imm8
24688     0/imm32/no-disp32
24689     0/imm32/no-xm32
24690     0/imm32/no-x32
24691     0x11/imm32/alloc-id:fake
24692     _Primitive-break-if-</imm32/next
24693 _Primitive-break-if-<:  # (payload primitive)
24694     0x11/imm32/alloc-id:fake:payload
24695     0x11/imm32/alloc-id:fake
24696     _string-break-if-</imm32/name
24697     0/imm32/no-inouts
24698     0/imm32/no-inouts
24699     0/imm32/no-outputs
24700     0/imm32/no-outputs
24701     0x11/imm32/alloc-id:fake
24702     _string_0f_8c_jump_break/imm32/subx-name
24703     0/imm32/no-rm32
24704     0/imm32/no-r32
24705     0/imm32/no-imm32
24706     0/imm32/no-imm8
24707     0/imm32/no-disp32
24708     0/imm32/no-xm32
24709     0/imm32/no-x32
24710     0x11/imm32/alloc-id:fake
24711     _Primitive-break-if->=/imm32/next
24712 _Primitive-break-if->=:  # (payload primitive)
24713     0x11/imm32/alloc-id:fake:payload
24714     0x11/imm32/alloc-id:fake
24715     _string-break-if->=/imm32/name
24716     0/imm32/no-inouts
24717     0/imm32/no-inouts
24718     0/imm32/no-outputs
24719     0/imm32/no-outputs
24720     0x11/imm32/alloc-id:fake
24721     _string_0f_8d_jump_break/imm32/subx-name
24722     0/imm32/no-rm32
24723     0/imm32/no-r32
24724     0/imm32/no-imm32
24725     0/imm32/no-imm8
24726     0/imm32/no-disp32
24727     0/imm32/no-xm32
24728     0/imm32/no-x32
24729     0x11/imm32/alloc-id:fake
24730     _Primitive-break-if-<=/imm32/next
24731 _Primitive-break-if-<=:  # (payload primitive)
24732     0x11/imm32/alloc-id:fake:payload
24733     0x11/imm32/alloc-id:fake
24734     _string-break-if-<=/imm32/name
24735     0/imm32/no-inouts
24736     0/imm32/no-inouts
24737     0/imm32/no-outputs
24738     0/imm32/no-outputs
24739     0x11/imm32/alloc-id:fake
24740     _string_0f_8e_jump_break/imm32/subx-name
24741     0/imm32/no-rm32
24742     0/imm32/no-r32
24743     0/imm32/no-imm32
24744     0/imm32/no-imm8
24745     0/imm32/no-disp32
24746     0/imm32/no-xm32
24747     0/imm32/no-x32
24748     0x11/imm32/alloc-id:fake
24749     _Primitive-break-if->/imm32/next
24750 _Primitive-break-if->:  # (payload primitive)
24751     0x11/imm32/alloc-id:fake:payload
24752     0x11/imm32/alloc-id:fake
24753     _string-break-if->/imm32/name
24754     0/imm32/no-inouts
24755     0/imm32/no-inouts
24756     0/imm32/no-outputs
24757     0/imm32/no-outputs
24758     0x11/imm32/alloc-id:fake
24759     _string_0f_8f_jump_break/imm32/subx-name
24760     0/imm32/no-rm32
24761     0/imm32/no-r32
24762     0/imm32/no-imm32
24763     0/imm32/no-imm8
24764     0/imm32/no-disp32
24765     0/imm32/no-xm32
24766     0/imm32/no-x32
24767     0x11/imm32/alloc-id:fake
24768     _Primitive-break/imm32/next
24769 _Primitive-break:  # (payload primitive)
24770     0x11/imm32/alloc-id:fake:payload
24771     0x11/imm32/alloc-id:fake
24772     _string-break/imm32/name
24773     0/imm32/no-inouts
24774     0/imm32/no-inouts
24775     0/imm32/no-outputs
24776     0/imm32/no-outputs
24777     0x11/imm32/alloc-id:fake
24778     _string_e9_jump_break/imm32/subx-name
24779     0/imm32/no-rm32
24780     0/imm32/no-r32
24781     0/imm32/no-imm32
24782     0/imm32/no-imm8
24783     0/imm32/no-disp32
24784     0/imm32/no-xm32
24785     0/imm32/no-x32
24786     0x11/imm32/alloc-id:fake
24787     _Primitive-loop-if-addr</imm32/next
24788 _Primitive-loop-if-addr<:  # (payload primitive)
24789     0x11/imm32/alloc-id:fake:payload
24790     0x11/imm32/alloc-id:fake
24791     _string-loop-if-addr</imm32/name
24792     0/imm32/no-inouts
24793     0/imm32/no-inouts
24794     0/imm32/no-outputs
24795     0/imm32/no-outputs
24796     0x11/imm32/alloc-id:fake
24797     _string_0f_82_jump_loop/imm32/subx-name
24798     0/imm32/no-rm32
24799     0/imm32/no-r32
24800     0/imm32/no-imm32
24801     0/imm32/no-imm8
24802     0/imm32/no-disp32
24803     0/imm32/no-xm32
24804     0/imm32/no-x32
24805     0x11/imm32/alloc-id:fake
24806     _Primitive-loop-if-addr>=/imm32/next
24807 _Primitive-loop-if-addr>=:  # (payload primitive)
24808     0x11/imm32/alloc-id:fake:payload
24809     0x11/imm32/alloc-id:fake
24810     _string-loop-if-addr>=/imm32/name
24811     0/imm32/no-inouts
24812     0/imm32/no-inouts
24813     0/imm32/no-outputs
24814     0/imm32/no-outputs
24815     0x11/imm32/alloc-id:fake
24816     _string_0f_83_jump_loop/imm32/subx-name
24817     0/imm32/no-rm32
24818     0/imm32/no-r32
24819     0/imm32/no-imm32
24820     0/imm32/no-imm8
24821     0/imm32/no-disp32
24822     0/imm32/no-xm32
24823     0/imm32/no-x32
24824     0x11/imm32/alloc-id:fake
24825     _Primitive-loop-if-=/imm32/next
24826 _Primitive-loop-if-=:  # (payload primitive)
24827     0x11/imm32/alloc-id:fake:payload
24828     0x11/imm32/alloc-id:fake
24829     _string-loop-if-=/imm32/name
24830     0/imm32/no-inouts
24831     0/imm32/no-inouts
24832     0/imm32/no-outputs
24833     0/imm32/no-outputs
24834     0x11/imm32/alloc-id:fake
24835     _string_0f_84_jump_loop/imm32/subx-name
24836     0/imm32/no-rm32
24837     0/imm32/no-r32
24838     0/imm32/no-imm32
24839     0/imm32/no-imm8
24840     0/imm32/no-disp32
24841     0/imm32/no-xm32
24842     0/imm32/no-x32
24843     0x11/imm32/alloc-id:fake
24844     _Primitive-loop-if-!=/imm32/next
24845 _Primitive-loop-if-!=:  # (payload primitive)
24846     0x11/imm32/alloc-id:fake:payload
24847     0x11/imm32/alloc-id:fake
24848     _string-loop-if-!=/imm32/name
24849     0/imm32/no-inouts
24850     0/imm32/no-inouts
24851     0/imm32/no-outputs
24852     0/imm32/no-outputs
24853     0x11/imm32/alloc-id:fake
24854     _string_0f_85_jump_loop/imm32/subx-name
24855     0/imm32/no-rm32
24856     0/imm32/no-r32
24857     0/imm32/no-imm32
24858     0/imm32/no-imm8
24859     0/imm32/no-disp32
24860     0/imm32/no-xm32
24861     0/imm32/no-x32
24862     0x11/imm32/alloc-id:fake
24863     _Primitive-loop-if-addr<=/imm32/next
24864 _Primitive-loop-if-addr<=:  # (payload primitive)
24865     0x11/imm32/alloc-id:fake:payload
24866     0x11/imm32/alloc-id:fake
24867     _string-loop-if-addr<=/imm32/name
24868     0/imm32/no-inouts
24869     0/imm32/no-inouts
24870     0/imm32/no-outputs
24871     0/imm32/no-outputs
24872     0x11/imm32/alloc-id:fake
24873     _string_0f_86_jump_loop/imm32/subx-name
24874     0/imm32/no-rm32
24875     0/imm32/no-r32
24876     0/imm32/no-imm32
24877     0/imm32/no-imm8
24878     0/imm32/no-disp32
24879     0/imm32/no-xm32
24880     0/imm32/no-x32
24881     0x11/imm32/alloc-id:fake
24882     _Primitive-loop-if-addr>/imm32/next
24883 _Primitive-loop-if-addr>:  # (payload primitive)
24884     0x11/imm32/alloc-id:fake:payload
24885     0x11/imm32/alloc-id:fake
24886     _string-loop-if-addr>/imm32/name
24887     0/imm32/no-inouts
24888     0/imm32/no-inouts
24889     0/imm32/no-outputs
24890     0/imm32/no-outputs
24891     0x11/imm32/alloc-id:fake
24892     _string_0f_87_jump_loop/imm32/subx-name
24893     0/imm32/no-rm32
24894     0/imm32/no-r32
24895     0/imm32/no-imm32
24896     0/imm32/no-imm8
24897     0/imm32/no-disp32
24898     0/imm32/no-xm32
24899     0/imm32/no-x32
24900     0x11/imm32/alloc-id:fake
24901     _Primitive-loop-if-</imm32/next
24902 _Primitive-loop-if-<:  # (payload primitive)
24903     0x11/imm32/alloc-id:fake:payload
24904     0x11/imm32/alloc-id:fake
24905     _string-loop-if-</imm32/name
24906     0/imm32/no-inouts
24907     0/imm32/no-inouts
24908     0/imm32/no-outputs
24909     0/imm32/no-outputs
24910     0x11/imm32/alloc-id:fake
24911     _string_0f_8c_jump_loop/imm32/subx-name
24912     0/imm32/no-rm32
24913     0/imm32/no-r32
24914     0/imm32/no-imm32
24915     0/imm32/no-imm8
24916     0/imm32/no-disp32
24917     0/imm32/no-xm32
24918     0/imm32/no-x32
24919     0x11/imm32/alloc-id:fake
24920     _Primitive-loop-if->=/imm32/next
24921 _Primitive-loop-if->=:  # (payload primitive)
24922     0x11/imm32/alloc-id:fake:payload
24923     0x11/imm32/alloc-id:fake
24924     _string-loop-if->=/imm32/name
24925     0/imm32/no-inouts
24926     0/imm32/no-inouts
24927     0/imm32/no-outputs
24928     0/imm32/no-outputs
24929     0x11/imm32/alloc-id:fake
24930     _string_0f_8d_jump_loop/imm32/subx-name
24931     0/imm32/no-rm32
24932     0/imm32/no-r32
24933     0/imm32/no-imm32
24934     0/imm32/no-imm8
24935     0/imm32/no-disp32
24936     0/imm32/no-xm32
24937     0/imm32/no-x32
24938     0x11/imm32/alloc-id:fake
24939     _Primitive-loop-if-<=/imm32/next
24940 _Primitive-loop-if-<=:  # (payload primitive)
24941     0x11/imm32/alloc-id:fake:payload
24942     0x11/imm32/alloc-id:fake
24943     _string-loop-if-<=/imm32/name
24944     0/imm32/no-inouts
24945     0/imm32/no-inouts
24946     0/imm32/no-outputs
24947     0/imm32/no-outputs
24948     0x11/imm32/alloc-id:fake
24949     _string_0f_8e_jump_loop/imm32/subx-name
24950     0/imm32/no-rm32
24951     0/imm32/no-r32
24952     0/imm32/no-imm32
24953     0/imm32/no-imm8
24954     0/imm32/no-disp32
24955     0/imm32/no-xm32
24956     0/imm32/no-x32
24957     0x11/imm32/alloc-id:fake
24958     _Primitive-loop-if->/imm32/next
24959 _Primitive-loop-if->:  # (payload primitive)
24960     0x11/imm32/alloc-id:fake:payload
24961     0x11/imm32/alloc-id:fake
24962     _string-loop-if->/imm32/name
24963     0/imm32/no-inouts
24964     0/imm32/no-inouts
24965     0/imm32/no-outputs
24966     0/imm32/no-outputs
24967     0x11/imm32/alloc-id:fake
24968     _string_0f_8f_jump_loop/imm32/subx-name
24969     0/imm32/no-rm32
24970     0/imm32/no-r32
24971     0/imm32/no-imm32
24972     0/imm32/no-imm8
24973     0/imm32/no-disp32
24974     0/imm32/no-xm32
24975     0/imm32/no-x32
24976     0x11/imm32/alloc-id:fake
24977     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
24978 _Primitive-loop:  # (payload primitive)
24979     0x11/imm32/alloc-id:fake:payload
24980     0x11/imm32/alloc-id:fake
24981     _string-loop/imm32/name
24982     0/imm32/no-inouts
24983     0/imm32/no-inouts
24984     0/imm32/no-outputs
24985     0/imm32/no-outputs
24986     0x11/imm32/alloc-id:fake
24987     _string_e9_jump_loop/imm32/subx-name
24988     0/imm32/no-rm32
24989     0/imm32/no-r32
24990     0/imm32/no-imm32
24991     0/imm32/no-imm8
24992     0/imm32/no-disp32
24993     0/imm32/no-xm32
24994     0/imm32/no-x32
24995     0x11/imm32/alloc-id:fake
24996     _Primitive-break-if-addr<-named/imm32/next
24997 # - branches to named blocks
24998 _Primitive-break-if-addr<-named:  # (payload primitive)
24999     0x11/imm32/alloc-id:fake:payload
25000     0x11/imm32/alloc-id:fake
25001     _string-break-if-addr</imm32/name
25002     0x11/imm32/alloc-id:fake
25003     Single-lit-var/imm32/inouts
25004     0/imm32/no-outputs
25005     0/imm32/no-outputs
25006     0x11/imm32/alloc-id:fake
25007     _string_0f_82_jump_label/imm32/subx-name
25008     0/imm32/no-rm32
25009     0/imm32/no-r32
25010     0/imm32/no-imm32
25011     0/imm32/no-imm8
25012     1/imm32/disp32-is-first-inout
25013     0/imm32/no-xm32
25014     0/imm32/no-x32
25015     0x11/imm32/alloc-id:fake
25016     _Primitive-break-if-addr>=-named/imm32/next
25017 _Primitive-break-if-addr>=-named:  # (payload primitive)
25018     0x11/imm32/alloc-id:fake:payload
25019     0x11/imm32/alloc-id:fake
25020     _string-break-if-addr>=/imm32/name
25021     0x11/imm32/alloc-id:fake
25022     Single-lit-var/imm32/inouts
25023     0/imm32/no-outputs
25024     0/imm32/no-outputs
25025     0x11/imm32/alloc-id:fake
25026     _string_0f_83_jump_label/imm32/subx-name
25027     0/imm32/no-rm32
25028     0/imm32/no-r32
25029     0/imm32/no-imm32
25030     0/imm32/no-imm8
25031     1/imm32/disp32-is-first-inout
25032     0/imm32/no-xm32
25033     0/imm32/no-x32
25034     0x11/imm32/alloc-id:fake
25035     _Primitive-break-if-=-named/imm32/next
25036 _Primitive-break-if-=-named:  # (payload primitive)
25037     0x11/imm32/alloc-id:fake:payload
25038     0x11/imm32/alloc-id:fake
25039     _string-break-if-=/imm32/name
25040     0x11/imm32/alloc-id:fake
25041     Single-lit-var/imm32/inouts
25042     0/imm32/no-outputs
25043     0/imm32/no-outputs
25044     0x11/imm32/alloc-id:fake
25045     _string_0f_84_jump_label/imm32/subx-name
25046     0/imm32/no-rm32
25047     0/imm32/no-r32
25048     0/imm32/no-imm32
25049     0/imm32/no-imm8
25050     1/imm32/disp32-is-first-inout
25051     0/imm32/no-xm32
25052     0/imm32/no-x32
25053     0x11/imm32/alloc-id:fake
25054     _Primitive-break-if-!=-named/imm32/next
25055 _Primitive-break-if-!=-named:  # (payload primitive)
25056     0x11/imm32/alloc-id:fake:payload
25057     0x11/imm32/alloc-id:fake
25058     _string-break-if-!=/imm32/name
25059     0x11/imm32/alloc-id:fake
25060     Single-lit-var/imm32/inouts
25061     0/imm32/no-outputs
25062     0/imm32/no-outputs
25063     0x11/imm32/alloc-id:fake
25064     _string_0f_85_jump_label/imm32/subx-name
25065     0/imm32/no-rm32
25066     0/imm32/no-r32
25067     0/imm32/no-imm32
25068     0/imm32/no-imm8
25069     1/imm32/disp32-is-first-inout
25070     0/imm32/no-xm32
25071     0/imm32/no-x32
25072     0x11/imm32/alloc-id:fake
25073     _Primitive-break-if-addr<=-named/imm32/next
25074 _Primitive-break-if-addr<=-named:  # (payload primitive)
25075     0x11/imm32/alloc-id:fake:payload
25076     0x11/imm32/alloc-id:fake
25077     _string-break-if-addr<=/imm32/name
25078     0x11/imm32/alloc-id:fake
25079     Single-lit-var/imm32/inouts
25080     0/imm32/no-outputs
25081     0/imm32/no-outputs
25082     0x11/imm32/alloc-id:fake
25083     _string_0f_86_jump_label/imm32/subx-name
25084     0/imm32/no-rm32
25085     0/imm32/no-r32
25086     0/imm32/no-imm32
25087     0/imm32/no-imm8
25088     1/imm32/disp32-is-first-inout
25089     0/imm32/no-xm32
25090     0/imm32/no-x32
25091     0x11/imm32/alloc-id:fake
25092     _Primitive-break-if-addr>-named/imm32/next
25093 _Primitive-break-if-addr>-named:  # (payload primitive)
25094     0x11/imm32/alloc-id:fake:payload
25095     0x11/imm32/alloc-id:fake
25096     _string-break-if-addr>/imm32/name
25097     0x11/imm32/alloc-id:fake
25098     Single-lit-var/imm32/inouts
25099     0/imm32/no-outputs
25100     0/imm32/no-outputs
25101     0x11/imm32/alloc-id:fake
25102     _string_0f_87_jump_label/imm32/subx-name
25103     0/imm32/no-rm32
25104     0/imm32/no-r32
25105     0/imm32/no-imm32
25106     0/imm32/no-imm8
25107     1/imm32/disp32-is-first-inout
25108     0/imm32/no-xm32
25109     0/imm32/no-x32
25110     0x11/imm32/alloc-id:fake
25111     _Primitive-break-if-<-named/imm32/next
25112 _Primitive-break-if-<-named:  # (payload primitive)
25113     0x11/imm32/alloc-id:fake:payload
25114     0x11/imm32/alloc-id:fake
25115     _string-break-if-</imm32/name
25116     0x11/imm32/alloc-id:fake
25117     Single-lit-var/imm32/inouts
25118     0/imm32/no-outputs
25119     0/imm32/no-outputs
25120     0x11/imm32/alloc-id:fake
25121     _string_0f_8c_jump_label/imm32/subx-name
25122     0/imm32/no-rm32
25123     0/imm32/no-r32
25124     0/imm32/no-imm32
25125     0/imm32/no-imm8
25126     1/imm32/disp32-is-first-inout
25127     0/imm32/no-xm32
25128     0/imm32/no-x32
25129     0x11/imm32/alloc-id:fake
25130     _Primitive-break-if->=-named/imm32/next
25131 _Primitive-break-if->=-named:  # (payload primitive)
25132     0x11/imm32/alloc-id:fake:payload
25133     0x11/imm32/alloc-id:fake
25134     _string-break-if->=/imm32/name
25135     0x11/imm32/alloc-id:fake
25136     Single-lit-var/imm32/inouts
25137     0/imm32/no-outputs
25138     0/imm32/no-outputs
25139     0x11/imm32/alloc-id:fake
25140     _string_0f_8d_jump_label/imm32/subx-name
25141     0/imm32/no-rm32
25142     0/imm32/no-r32
25143     0/imm32/no-imm32
25144     0/imm32/no-imm8
25145     1/imm32/disp32-is-first-inout
25146     0/imm32/no-xm32
25147     0/imm32/no-x32
25148     0x11/imm32/alloc-id:fake
25149     _Primitive-break-if-<=-named/imm32/next
25150 _Primitive-break-if-<=-named:  # (payload primitive)
25151     0x11/imm32/alloc-id:fake:payload
25152     0x11/imm32/alloc-id:fake
25153     _string-break-if-<=/imm32/name
25154     0x11/imm32/alloc-id:fake
25155     Single-lit-var/imm32/inouts
25156     0/imm32/no-outputs
25157     0/imm32/no-outputs
25158     0x11/imm32/alloc-id:fake
25159     _string_0f_8e_jump_label/imm32/subx-name
25160     0/imm32/no-rm32
25161     0/imm32/no-r32
25162     0/imm32/no-imm32
25163     0/imm32/no-imm8
25164     1/imm32/disp32-is-first-inout
25165     0/imm32/no-xm32
25166     0/imm32/no-x32
25167     0x11/imm32/alloc-id:fake
25168     _Primitive-break-if->-named/imm32/next
25169 _Primitive-break-if->-named:  # (payload primitive)
25170     0x11/imm32/alloc-id:fake:payload
25171     0x11/imm32/alloc-id:fake
25172     _string-break-if->/imm32/name
25173     0x11/imm32/alloc-id:fake
25174     Single-lit-var/imm32/inouts
25175     0/imm32/no-outputs
25176     0/imm32/no-outputs
25177     0x11/imm32/alloc-id:fake
25178     _string_0f_8f_jump_label/imm32/subx-name
25179     0/imm32/no-rm32
25180     0/imm32/no-r32
25181     0/imm32/no-imm32
25182     0/imm32/no-imm8
25183     1/imm32/disp32-is-first-inout
25184     0/imm32/no-xm32
25185     0/imm32/no-x32
25186     0x11/imm32/alloc-id:fake
25187     _Primitive-break-named/imm32/next
25188 _Primitive-break-named:  # (payload primitive)
25189     0x11/imm32/alloc-id:fake:payload
25190     0x11/imm32/alloc-id:fake
25191     _string-break/imm32/name
25192     0x11/imm32/alloc-id:fake
25193     Single-lit-var/imm32/inouts
25194     0/imm32/no-outputs
25195     0/imm32/no-outputs
25196     0x11/imm32/alloc-id:fake
25197     _string_e9_jump_label/imm32/subx-name
25198     0/imm32/no-rm32
25199     0/imm32/no-r32
25200     0/imm32/no-imm32
25201     0/imm32/no-imm8
25202     1/imm32/disp32-is-first-inout
25203     0/imm32/no-xm32
25204     0/imm32/no-x32
25205     0x11/imm32/alloc-id:fake
25206     _Primitive-loop-if-addr<-named/imm32/next
25207 _Primitive-loop-if-addr<-named:  # (payload primitive)
25208     0x11/imm32/alloc-id:fake:payload
25209     0x11/imm32/alloc-id:fake
25210     _string-loop-if-addr</imm32/name
25211     0x11/imm32/alloc-id:fake
25212     Single-lit-var/imm32/inouts
25213     0/imm32/no-outputs
25214     0/imm32/no-outputs
25215     0x11/imm32/alloc-id:fake
25216     _string_0f_82_jump_label/imm32/subx-name
25217     0/imm32/no-rm32
25218     0/imm32/no-r32
25219     0/imm32/no-imm32
25220     0/imm32/no-imm8
25221     1/imm32/disp32-is-first-inout
25222     0/imm32/no-xm32
25223     0/imm32/no-x32
25224     0x11/imm32/alloc-id:fake
25225     _Primitive-loop-if-addr>=-named/imm32/next
25226 _Primitive-loop-if-addr>=-named:  # (payload primitive)
25227     0x11/imm32/alloc-id:fake:payload
25228     0x11/imm32/alloc-id:fake
25229     _string-loop-if-addr>=/imm32/name
25230     0x11/imm32/alloc-id:fake
25231     Single-lit-var/imm32/inouts
25232     0/imm32/no-outputs
25233     0/imm32/no-outputs
25234     0x11/imm32/alloc-id:fake
25235     _string_0f_83_jump_label/imm32/subx-name
25236     0/imm32/no-rm32
25237     0/imm32/no-r32
25238     0/imm32/no-imm32
25239     0/imm32/no-imm8
25240     1/imm32/disp32-is-first-inout
25241     0/imm32/no-xm32
25242     0/imm32/no-x32
25243     0x11/imm32/alloc-id:fake
25244     _Primitive-loop-if-=-named/imm32/next
25245 _Primitive-loop-if-=-named:  # (payload primitive)
25246     0x11/imm32/alloc-id:fake:payload
25247     0x11/imm32/alloc-id:fake
25248     _string-loop-if-=/imm32/name
25249     0x11/imm32/alloc-id:fake
25250     Single-lit-var/imm32/inouts
25251     0/imm32/no-outputs
25252     0/imm32/no-outputs
25253     0x11/imm32/alloc-id:fake
25254     _string_0f_84_jump_label/imm32/subx-name
25255     0/imm32/no-rm32
25256     0/imm32/no-r32
25257     0/imm32/no-imm32
25258     0/imm32/no-imm8
25259     1/imm32/disp32-is-first-inout
25260     0/imm32/no-xm32
25261     0/imm32/no-x32
25262     0x11/imm32/alloc-id:fake
25263     _Primitive-loop-if-!=-named/imm32/next
25264 _Primitive-loop-if-!=-named:  # (payload primitive)
25265     0x11/imm32/alloc-id:fake:payload
25266     0x11/imm32/alloc-id:fake
25267     _string-loop-if-!=/imm32/name
25268     0x11/imm32/alloc-id:fake
25269     Single-lit-var/imm32/inouts
25270     0/imm32/no-outputs
25271     0/imm32/no-outputs
25272     0x11/imm32/alloc-id:fake
25273     _string_0f_85_jump_label/imm32/subx-name
25274     0/imm32/no-rm32
25275     0/imm32/no-r32
25276     0/imm32/no-imm32
25277     0/imm32/no-imm8
25278     1/imm32/disp32-is-first-inout
25279     0/imm32/no-xm32
25280     0/imm32/no-x32
25281     0x11/imm32/alloc-id:fake
25282     _Primitive-loop-if-addr<=-named/imm32/next
25283 _Primitive-loop-if-addr<=-named:  # (payload primitive)
25284     0x11/imm32/alloc-id:fake:payload
25285     0x11/imm32/alloc-id:fake
25286     _string-loop-if-addr<=/imm32/name
25287     0x11/imm32/alloc-id:fake
25288     Single-lit-var/imm32/inouts
25289     0/imm32/no-outputs
25290     0/imm32/no-outputs
25291     0x11/imm32/alloc-id:fake
25292     _string_0f_86_jump_label/imm32/subx-name
25293     0/imm32/no-rm32
25294     0/imm32/no-r32
25295     0/imm32/no-imm32
25296     0/imm32/no-imm8
25297     1/imm32/disp32-is-first-inout
25298     0/imm32/no-xm32
25299     0/imm32/no-x32
25300     0x11/imm32/alloc-id:fake
25301     _Primitive-loop-if-addr>-named/imm32/next
25302 _Primitive-loop-if-addr>-named:  # (payload primitive)
25303     0x11/imm32/alloc-id:fake:payload
25304     0x11/imm32/alloc-id:fake
25305     _string-loop-if-addr>/imm32/name
25306     0x11/imm32/alloc-id:fake
25307     Single-lit-var/imm32/inouts
25308     0/imm32/no-outputs
25309     0/imm32/no-outputs
25310     0x11/imm32/alloc-id:fake
25311     _string_0f_87_jump_label/imm32/subx-name
25312     0/imm32/no-rm32
25313     0/imm32/no-r32
25314     0/imm32/no-imm32
25315     0/imm32/no-imm8
25316     1/imm32/disp32-is-first-inout
25317     0/imm32/no-xm32
25318     0/imm32/no-x32
25319     0x11/imm32/alloc-id:fake
25320     _Primitive-loop-if-<-named/imm32/next
25321 _Primitive-loop-if-<-named:  # (payload primitive)
25322     0x11/imm32/alloc-id:fake:payload
25323     0x11/imm32/alloc-id:fake
25324     _string-loop-if-</imm32/name
25325     0x11/imm32/alloc-id:fake
25326     Single-lit-var/imm32/inouts
25327     0/imm32/no-outputs
25328     0/imm32/no-outputs
25329     0x11/imm32/alloc-id:fake
25330     _string_0f_8c_jump_label/imm32/subx-name
25331     0/imm32/no-rm32
25332     0/imm32/no-r32
25333     0/imm32/no-imm32
25334     0/imm32/no-imm8
25335     1/imm32/disp32-is-first-inout
25336     0/imm32/no-xm32
25337     0/imm32/no-x32
25338     0x11/imm32/alloc-id:fake
25339     _Primitive-loop-if->=-named/imm32/next
25340 _Primitive-loop-if->=-named:  # (payload primitive)
25341     0x11/imm32/alloc-id:fake:payload
25342     0x11/imm32/alloc-id:fake
25343     _string-loop-if->=/imm32/name
25344     0x11/imm32/alloc-id:fake
25345     Single-lit-var/imm32/inouts
25346     0/imm32/no-outputs
25347     0/imm32/no-outputs
25348     0x11/imm32/alloc-id:fake
25349     _string_0f_8d_jump_label/imm32/subx-name
25350     0/imm32/no-rm32
25351     0/imm32/no-r32
25352     0/imm32/no-imm32
25353     0/imm32/no-imm8
25354     1/imm32/disp32-is-first-inout
25355     0/imm32/no-xm32
25356     0/imm32/no-x32
25357     0x11/imm32/alloc-id:fake
25358     _Primitive-loop-if-<=-named/imm32/next
25359 _Primitive-loop-if-<=-named:  # (payload primitive)
25360     0x11/imm32/alloc-id:fake:payload
25361     0x11/imm32/alloc-id:fake
25362     _string-loop-if-<=/imm32/name
25363     0x11/imm32/alloc-id:fake
25364     Single-lit-var/imm32/inouts
25365     0/imm32/no-outputs
25366     0/imm32/no-outputs
25367     0x11/imm32/alloc-id:fake
25368     _string_0f_8e_jump_label/imm32/subx-name
25369     0/imm32/no-rm32
25370     0/imm32/no-r32
25371     0/imm32/no-imm32
25372     0/imm32/no-imm8
25373     1/imm32/disp32-is-first-inout
25374     0/imm32/no-xm32
25375     0/imm32/no-x32
25376     0x11/imm32/alloc-id:fake
25377     _Primitive-loop-if->-named/imm32/next
25378 _Primitive-loop-if->-named:  # (payload primitive)
25379     0x11/imm32/alloc-id:fake:payload
25380     0x11/imm32/alloc-id:fake
25381     _string-loop-if->/imm32/name
25382     0x11/imm32/alloc-id:fake
25383     Single-lit-var/imm32/inouts
25384     0/imm32/no-outputs
25385     0/imm32/no-outputs
25386     0x11/imm32/alloc-id:fake
25387     _string_0f_8f_jump_label/imm32/subx-name
25388     0/imm32/no-rm32
25389     0/imm32/no-r32
25390     0/imm32/no-imm32
25391     0/imm32/no-imm8
25392     1/imm32/disp32-is-first-inout
25393     0/imm32/no-xm32
25394     0/imm32/no-x32
25395     0x11/imm32/alloc-id:fake
25396     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
25397 _Primitive-loop-named:  # (payload primitive)
25398     0x11/imm32/alloc-id:fake:payload
25399     0x11/imm32/alloc-id:fake
25400     _string-loop/imm32/name
25401     0x11/imm32/alloc-id:fake
25402     Single-lit-var/imm32/inouts
25403     0/imm32/no-outputs
25404     0/imm32/no-outputs
25405     0x11/imm32/alloc-id:fake
25406     _string_e9_jump_label/imm32/subx-name
25407     0/imm32/no-rm32
25408     0/imm32/no-r32
25409     0/imm32/no-imm32
25410     0/imm32/no-imm8
25411     1/imm32/disp32-is-first-inout
25412     0/imm32/no-xm32
25413     0/imm32/no-x32
25414     0x11/imm32/alloc-id:fake
25415     _Primitive-break-if-float</imm32/next
25416 # - branches based on floating-point comparisons
25417 _Primitive-break-if-float<:  # (payload primitive)
25418     0x11/imm32/alloc-id:fake:payload
25419     0x11/imm32/alloc-id:fake
25420     _string-break-if-float</imm32/name
25421     0/imm32/no-inouts
25422     0/imm32/no-inouts
25423     0/imm32/no-outputs
25424     0/imm32/no-outputs
25425     0x11/imm32/alloc-id:fake
25426     _string_0f_82_jump_break/imm32/subx-name
25427     0/imm32/no-rm32
25428     0/imm32/no-r32
25429     0/imm32/no-imm32
25430     0/imm32/no-imm8
25431     0/imm32/no-disp32
25432     0/imm32/no-xm32
25433     0/imm32/no-x32
25434     0x11/imm32/alloc-id:fake
25435     _Primitive-break-if-float>=/imm32/next
25436 _Primitive-break-if-float>=:  # (payload primitive)
25437     0x11/imm32/alloc-id:fake:payload
25438     0x11/imm32/alloc-id:fake
25439     _string-break-if-float>=/imm32/name
25440     0/imm32/no-inouts
25441     0/imm32/no-inouts
25442     0/imm32/no-outputs
25443     0/imm32/no-outputs
25444     0x11/imm32/alloc-id:fake
25445     _string_0f_83_jump_break/imm32/subx-name
25446     0/imm32/no-rm32
25447     0/imm32/no-r32
25448     0/imm32/no-imm32
25449     0/imm32/no-imm8
25450     0/imm32/no-disp32
25451     0/imm32/no-xm32
25452     0/imm32/no-x32
25453     0x11/imm32/alloc-id:fake
25454     _Primitive-break-if-float<=/imm32/next
25455 _Primitive-break-if-float<=:  # (payload primitive)
25456     0x11/imm32/alloc-id:fake:payload
25457     0x11/imm32/alloc-id:fake
25458     _string-break-if-float<=/imm32/name
25459     0/imm32/no-inouts
25460     0/imm32/no-inouts
25461     0/imm32/no-outputs
25462     0/imm32/no-outputs
25463     0x11/imm32/alloc-id:fake
25464     _string_0f_86_jump_break/imm32/subx-name
25465     0/imm32/no-rm32
25466     0/imm32/no-r32
25467     0/imm32/no-imm32
25468     0/imm32/no-imm8
25469     0/imm32/no-disp32
25470     0/imm32/no-xm32
25471     0/imm32/no-x32
25472     0x11/imm32/alloc-id:fake
25473     _Primitive-break-if-float>/imm32/next
25474 _Primitive-break-if-float>:  # (payload primitive)
25475     0x11/imm32/alloc-id:fake:payload
25476     0x11/imm32/alloc-id:fake
25477     _string-break-if-float>/imm32/name
25478     0/imm32/no-inouts
25479     0/imm32/no-inouts
25480     0/imm32/no-outputs
25481     0/imm32/no-outputs
25482     0x11/imm32/alloc-id:fake
25483     _string_0f_87_jump_break/imm32/subx-name
25484     0/imm32/no-rm32
25485     0/imm32/no-r32
25486     0/imm32/no-imm32
25487     0/imm32/no-imm8
25488     0/imm32/no-disp32
25489     0/imm32/no-xm32
25490     0/imm32/no-x32
25491     0x11/imm32/alloc-id:fake
25492     _Primitive-loop-if-float</imm32/next
25493 _Primitive-loop-if-float<:  # (payload primitive)
25494     0x11/imm32/alloc-id:fake:payload
25495     0x11/imm32/alloc-id:fake
25496     _string-loop-if-float</imm32/name
25497     0/imm32/no-inouts
25498     0/imm32/no-inouts
25499     0/imm32/no-outputs
25500     0/imm32/no-outputs
25501     0x11/imm32/alloc-id:fake
25502     _string_0f_82_jump_loop/imm32/subx-name
25503     0/imm32/no-rm32
25504     0/imm32/no-r32
25505     0/imm32/no-imm32
25506     0/imm32/no-imm8
25507     0/imm32/no-disp32
25508     0/imm32/no-xm32
25509     0/imm32/no-x32
25510     0x11/imm32/alloc-id:fake
25511     _Primitive-loop-if-float>=/imm32/next
25512 _Primitive-loop-if-float>=:  # (payload primitive)
25513     0x11/imm32/alloc-id:fake:payload
25514     0x11/imm32/alloc-id:fake
25515     _string-loop-if-float>=/imm32/name
25516     0/imm32/no-inouts
25517     0/imm32/no-inouts
25518     0/imm32/no-outputs
25519     0/imm32/no-outputs
25520     0x11/imm32/alloc-id:fake
25521     _string_0f_83_jump_loop/imm32/subx-name
25522     0/imm32/no-rm32
25523     0/imm32/no-r32
25524     0/imm32/no-imm32
25525     0/imm32/no-imm8
25526     0/imm32/no-disp32
25527     0/imm32/no-xm32
25528     0/imm32/no-x32
25529     0x11/imm32/alloc-id:fake
25530     _Primitive-loop-if-float<=/imm32/next
25531 _Primitive-loop-if-float<=:  # (payload primitive)
25532     0x11/imm32/alloc-id:fake:payload
25533     0x11/imm32/alloc-id:fake
25534     _string-loop-if-float<=/imm32/name
25535     0/imm32/no-inouts
25536     0/imm32/no-inouts
25537     0/imm32/no-outputs
25538     0/imm32/no-outputs
25539     0x11/imm32/alloc-id:fake
25540     _string_0f_86_jump_loop/imm32/subx-name
25541     0/imm32/no-rm32
25542     0/imm32/no-r32
25543     0/imm32/no-imm32
25544     0/imm32/no-imm8
25545     0/imm32/no-disp32
25546     0/imm32/no-xm32
25547     0/imm32/no-x32
25548     0x11/imm32/alloc-id:fake
25549     _Primitive-loop-if-float>/imm32/next
25550 _Primitive-loop-if-float>:  # (payload primitive)
25551     0x11/imm32/alloc-id:fake:payload
25552     0x11/imm32/alloc-id:fake
25553     _string-loop-if-float>/imm32/name
25554     0/imm32/no-inouts
25555     0/imm32/no-inouts
25556     0/imm32/no-outputs
25557     0/imm32/no-outputs
25558     0x11/imm32/alloc-id:fake
25559     _string_0f_87_jump_loop/imm32/subx-name
25560     0/imm32/no-rm32
25561     0/imm32/no-r32
25562     0/imm32/no-imm32
25563     0/imm32/no-imm8
25564     0/imm32/no-disp32
25565     0/imm32/no-xm32
25566     0/imm32/no-x32
25567     0x11/imm32/alloc-id:fake
25568     _Primitive-break-if-float<-named/imm32/next
25569 _Primitive-break-if-float<-named:  # (payload primitive)
25570     0x11/imm32/alloc-id:fake:payload
25571     0x11/imm32/alloc-id:fake
25572     _string-break-if-float</imm32/name
25573     0x11/imm32/alloc-id:fake
25574     Single-lit-var/imm32/inouts
25575     0/imm32/no-outputs
25576     0/imm32/no-outputs
25577     0x11/imm32/alloc-id:fake
25578     _string_0f_82_jump_label/imm32/subx-name
25579     0/imm32/no-rm32
25580     0/imm32/no-r32
25581     0/imm32/no-imm32
25582     0/imm32/no-imm8
25583     1/imm32/disp32-is-first-inout
25584     0/imm32/no-xm32
25585     0/imm32/no-x32
25586     0x11/imm32/alloc-id:fake
25587     _Primitive-break-if-float>=-named/imm32/next
25588 _Primitive-break-if-float>=-named:  # (payload primitive)
25589     0x11/imm32/alloc-id:fake:payload
25590     0x11/imm32/alloc-id:fake
25591     _string-break-if-float>=/imm32/name
25592     0x11/imm32/alloc-id:fake
25593     Single-lit-var/imm32/inouts
25594     0/imm32/no-outputs
25595     0/imm32/no-outputs
25596     0x11/imm32/alloc-id:fake
25597     _string_0f_83_jump_label/imm32/subx-name
25598     0/imm32/no-rm32
25599     0/imm32/no-r32
25600     0/imm32/no-imm32
25601     0/imm32/no-imm8
25602     1/imm32/disp32-is-first-inout
25603     0/imm32/no-xm32
25604     0/imm32/no-x32
25605     0x11/imm32/alloc-id:fake
25606     _Primitive-break-if-float<=-named/imm32/next
25607 _Primitive-break-if-float<=-named:  # (payload primitive)
25608     0x11/imm32/alloc-id:fake:payload
25609     0x11/imm32/alloc-id:fake
25610     _string-break-if-float<=/imm32/name
25611     0x11/imm32/alloc-id:fake
25612     Single-lit-var/imm32/inouts
25613     0/imm32/no-outputs
25614     0/imm32/no-outputs
25615     0x11/imm32/alloc-id:fake
25616     _string_0f_86_jump_label/imm32/subx-name
25617     0/imm32/no-rm32
25618     0/imm32/no-r32
25619     0/imm32/no-imm32
25620     0/imm32/no-imm8
25621     1/imm32/disp32-is-first-inout
25622     0/imm32/no-xm32
25623     0/imm32/no-x32
25624     0x11/imm32/alloc-id:fake
25625     _Primitive-break-if-float>-named/imm32/next
25626 _Primitive-break-if-float>-named:  # (payload primitive)
25627     0x11/imm32/alloc-id:fake:payload
25628     0x11/imm32/alloc-id:fake
25629     _string-break-if-float>/imm32/name
25630     0x11/imm32/alloc-id:fake
25631     Single-lit-var/imm32/inouts
25632     0/imm32/no-outputs
25633     0/imm32/no-outputs
25634     0x11/imm32/alloc-id:fake
25635     _string_0f_87_jump_label/imm32/subx-name
25636     0/imm32/no-rm32
25637     0/imm32/no-r32
25638     0/imm32/no-imm32
25639     0/imm32/no-imm8
25640     1/imm32/disp32-is-first-inout
25641     0/imm32/no-xm32
25642     0/imm32/no-x32
25643     0x11/imm32/alloc-id:fake
25644     _Primitive-loop-if-float<-named/imm32/next
25645 _Primitive-loop-if-float<-named:  # (payload primitive)
25646     0x11/imm32/alloc-id:fake:payload
25647     0x11/imm32/alloc-id:fake
25648     _string-loop-if-float</imm32/name
25649     0x11/imm32/alloc-id:fake
25650     Single-lit-var/imm32/inouts
25651     0/imm32/no-outputs
25652     0/imm32/no-outputs
25653     0x11/imm32/alloc-id:fake
25654     _string_0f_82_jump_label/imm32/subx-name
25655     0/imm32/no-rm32
25656     0/imm32/no-r32
25657     0/imm32/no-imm32
25658     0/imm32/no-imm8
25659     1/imm32/disp32-is-first-inout
25660     0/imm32/no-xm32
25661     0/imm32/no-x32
25662     0x11/imm32/alloc-id:fake
25663     _Primitive-loop-if-float>=-named/imm32/next
25664 _Primitive-loop-if-float>=-named:  # (payload primitive)
25665     0x11/imm32/alloc-id:fake:payload
25666     0x11/imm32/alloc-id:fake
25667     _string-loop-if-float>=/imm32/name
25668     0x11/imm32/alloc-id:fake
25669     Single-lit-var/imm32/inouts
25670     0/imm32/no-outputs
25671     0/imm32/no-outputs
25672     0x11/imm32/alloc-id:fake
25673     _string_0f_83_jump_label/imm32/subx-name
25674     0/imm32/no-rm32
25675     0/imm32/no-r32
25676     0/imm32/no-imm32
25677     0/imm32/no-imm8
25678     1/imm32/disp32-is-first-inout
25679     0/imm32/no-xm32
25680     0/imm32/no-x32
25681     0x11/imm32/alloc-id:fake
25682     _Primitive-loop-if-float<=-named/imm32/next
25683 _Primitive-loop-if-float<=-named:  # (payload primitive)
25684     0x11/imm32/alloc-id:fake:payload
25685     0x11/imm32/alloc-id:fake
25686     _string-loop-if-float<=/imm32/name
25687     0x11/imm32/alloc-id:fake
25688     Single-lit-var/imm32/inouts
25689     0/imm32/no-outputs
25690     0/imm32/no-outputs
25691     0x11/imm32/alloc-id:fake
25692     _string_0f_86_jump_label/imm32/subx-name
25693     0/imm32/no-rm32
25694     0/imm32/no-r32
25695     0/imm32/no-imm32
25696     0/imm32/no-imm8
25697     1/imm32/disp32-is-first-inout
25698     0/imm32/no-xm32
25699     0/imm32/no-x32
25700     0x11/imm32/alloc-id:fake
25701     _Primitive-loop-if-float>-named/imm32/next
25702 _Primitive-loop-if-float>-named:  # (payload primitive)
25703     0x11/imm32/alloc-id:fake:payload
25704     0x11/imm32/alloc-id:fake
25705     _string-loop-if-float>/imm32/name
25706     0x11/imm32/alloc-id:fake
25707     Single-lit-var/imm32/inouts
25708     0/imm32/no-outputs
25709     0/imm32/no-outputs
25710     0x11/imm32/alloc-id:fake
25711     _string_0f_87_jump_label/imm32/subx-name
25712     0/imm32/no-rm32
25713     0/imm32/no-r32
25714     0/imm32/no-imm32
25715     0/imm32/no-imm8
25716     1/imm32/disp32-is-first-inout
25717     0/imm32/no-xm32
25718     0/imm32/no-x32
25719     0/imm32/next
25720     0/imm32/next
25721 
25722 # string literals for Mu instructions
25723 _string-add:  # (payload array byte)
25724     0x11/imm32/alloc-id:fake:payload
25725     # "add"
25726     0x3/imm32/size
25727     0x61/a 0x64/d 0x64/d
25728 _string-address:  # (payload array byte)
25729     0x11/imm32/alloc-id:fake:payload
25730     # "address"
25731     0x7/imm32/size
25732     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
25733 _string-add-to:  # (payload array byte)
25734     0x11/imm32/alloc-id:fake:payload
25735     # "add-to"
25736     0x6/imm32/size
25737     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
25738 _string-and:  # (payload array byte)
25739     0x11/imm32/alloc-id:fake:payload
25740     # "and"
25741     0x3/imm32/size
25742     0x61/a 0x6e/n 0x64/d
25743 _string-and-with:  # (payload array byte)
25744     0x11/imm32/alloc-id:fake:payload
25745     # "and-with"
25746     0x8/imm32/size
25747     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
25748 _string-break:  # (payload array byte)
25749     0x11/imm32/alloc-id:fake:payload
25750     # "break"
25751     0x5/imm32/size
25752     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
25753 _string-break-if-<:  # (payload array byte)
25754     0x11/imm32/alloc-id:fake:payload
25755     # "break-if-<"
25756     0xa/imm32/size
25757     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
25758 _string-break-if-<=:  # (payload array byte)
25759     0x11/imm32/alloc-id:fake:payload
25760     # "break-if-<="
25761     0xb/imm32/size
25762     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
25763 _string-break-if-=:  # (payload array byte)
25764     0x11/imm32/alloc-id:fake:payload
25765     # "break-if-="
25766     0xa/imm32/size
25767     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
25768 _string-break-if->:  # (payload array byte)
25769     0x11/imm32/alloc-id:fake:payload
25770     # "break-if->"
25771     0xa/imm32/size
25772     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
25773 _string-break-if->=:  # (payload array byte)
25774     0x11/imm32/alloc-id:fake:payload
25775     # "break-if->="
25776     0xb/imm32/size
25777     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
25778 _string-break-if-!=:  # (payload array byte)
25779     0x11/imm32/alloc-id:fake:payload
25780     # "break-if-!="
25781     0xb/imm32/size
25782     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
25783 _string-break-if-addr<:  # (payload array byte)
25784     0x11/imm32/alloc-id:fake:payload
25785     # "break-if-addr<"
25786     0xe/imm32/size
25787     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/<
25788 _string-break-if-addr<=:  # (payload array byte)
25789     0x11/imm32/alloc-id:fake:payload
25790     # "break-if-addr<="
25791     0xf/imm32/size
25792     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/=
25793 _string-break-if-addr>:  # (payload array byte)
25794     0x11/imm32/alloc-id:fake:payload
25795     # "break-if-addr>"
25796     0xe/imm32/size
25797     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/>
25798 _string-break-if-addr>=:  # (payload array byte)
25799     0x11/imm32/alloc-id:fake:payload
25800     # "break-if-addr>="
25801     0xf/imm32/size
25802     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/=
25803 _string-break-if-float<:  # (payload array byte)
25804     0x11/imm32/alloc-id:fake:payload
25805     # "break-if-float<"
25806     0xf/imm32/size
25807     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/<
25808 _string-break-if-float<=:  # (payload array byte)
25809     0x11/imm32/alloc-id:fake:payload
25810     # "break-if-float<="
25811     0x10/imm32/size
25812     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/=
25813 _string-break-if-float>:  # (payload array byte)
25814     0x11/imm32/alloc-id:fake:payload
25815     # "break-if-float>"
25816     0xf/imm32/size
25817     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/>
25818 _string-break-if-float>=:  # (payload array byte)
25819     0x11/imm32/alloc-id:fake:payload
25820     # "break-if-float>="
25821     0x10/imm32/size
25822     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/=
25823 _string-compare:  # (payload array byte)
25824     0x11/imm32/alloc-id:fake:payload
25825     # "compare"
25826     0x7/imm32/size
25827     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
25828 _string-copy:  # (payload array byte)
25829     0x11/imm32/alloc-id:fake:payload
25830     # "copy"
25831     0x4/imm32/size
25832     0x63/c 0x6f/o 0x70/p 0x79/y
25833 _string-copy-to:  # (payload array byte)
25834     0x11/imm32/alloc-id:fake:payload
25835     # "copy-to"
25836     0x7/imm32/size
25837     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
25838 _string-copy-byte:
25839     0x11/imm32/alloc-id:fake:payload
25840     # "copy-byte"
25841     0x9/imm32/size
25842     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
25843 _string-copy-byte-to:
25844     0x11/imm32/alloc-id:fake:payload
25845     # "copy-byte-to"
25846     0xc/imm32/size
25847     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
25848 _string-decrement:  # (payload array byte)
25849     0x11/imm32/alloc-id:fake:payload
25850     # "decrement"
25851     0x9/imm32/size
25852     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
25853 _string-increment:  # (payload array byte)
25854     0x11/imm32/alloc-id:fake:payload
25855     # "increment"
25856     0x9/imm32/size
25857     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
25858 _string-loop:  # (payload array byte)
25859     0x11/imm32/alloc-id:fake:payload
25860     # "loop"
25861     0x4/imm32/size
25862     0x6c/l 0x6f/o 0x6f/o 0x70/p
25863 _string-loop-if-<:  # (payload array byte)
25864     0x11/imm32/alloc-id:fake:payload
25865     # "loop-if-<"
25866     0x9/imm32/size
25867     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
25868 _string-loop-if-<=:  # (payload array byte)
25869     0x11/imm32/alloc-id:fake:payload
25870     # "loop-if-<="
25871     0xa/imm32/size
25872     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
25873 _string-loop-if-=:  # (payload array byte)
25874     0x11/imm32/alloc-id:fake:payload
25875     # "loop-if-="
25876     0x9/imm32/size
25877     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
25878 _string-loop-if->:  # (payload array byte)
25879     0x11/imm32/alloc-id:fake:payload
25880     # "loop-if->"
25881     0x9/imm32/size
25882     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
25883 _string-loop-if->=:  # (payload array byte)
25884     0x11/imm32/alloc-id:fake:payload
25885     # "loop-if->="
25886     0xa/imm32/size
25887     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
25888 _string-loop-if-!=:  # (payload array byte)
25889     0x11/imm32/alloc-id:fake:payload
25890     # "loop-if-!="
25891     0xa/imm32/size
25892     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
25893 _string-loop-if-addr<:  # (payload array byte)
25894     0x11/imm32/alloc-id:fake:payload
25895     # "loop-if-addr<"
25896     0xd/imm32/size
25897     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/<
25898 _string-loop-if-addr<=:  # (payload array byte)
25899     0x11/imm32/alloc-id:fake:payload
25900     # "loop-if-addr<="
25901     0xe/imm32/size
25902     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/=
25903 _string-loop-if-addr>:  # (payload array byte)
25904     0x11/imm32/alloc-id:fake:payload
25905     # "loop-if-addr>"
25906     0xd/imm32/size
25907     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/>
25908 _string-loop-if-addr>=:  # (payload array byte)
25909     0x11/imm32/alloc-id:fake:payload
25910     # "loop-if-addr>="
25911     0xe/imm32/size
25912     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/=
25913 _string-loop-if-float<:  # (payload array byte)
25914     0x11/imm32/alloc-id:fake:payload
25915     # "loop-if-float<"
25916     0xe/imm32/size
25917     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/<
25918 _string-loop-if-float<=:  # (payload array byte)
25919     0x11/imm32/alloc-id:fake:payload
25920     # "loop-if-float<="
25921     0xf/imm32/size
25922     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/=
25923 _string-loop-if-float>:  # (payload array byte)
25924     0x11/imm32/alloc-id:fake:payload
25925     # "loop-if-float>"
25926     0xe/imm32/size
25927     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/>
25928 _string-loop-if-float>=:  # (payload array byte)
25929     0x11/imm32/alloc-id:fake:payload
25930     # "loop-if-float>="
25931     0xf/imm32/size
25932     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/=
25933 _string-multiply:  # (payload array byte)
25934     0x11/imm32/alloc-id:fake:payload
25935     # "multiply"
25936     0x8/imm32/size
25937     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
25938 _string-convert:  # (payload array byte)
25939     0x11/imm32/alloc-id:fake:payload
25940     # "convert"
25941     0x7/imm32/size
25942     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
25943 _string-truncate:  # (payload array byte)
25944     0x11/imm32/alloc-id:fake:payload
25945     # "truncate"
25946     0x8/imm32/size
25947     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
25948 _string-reinterpret:  # (payload array byte)
25949     0x11/imm32/alloc-id:fake:payload
25950     # "reinterpret"
25951     0xb/imm32/size
25952     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
25953 _string-divide:
25954     0x11/imm32/alloc-id:fake:payload
25955     # "divide"
25956     0x6/imm32/size
25957     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
25958 _string-max:
25959     0x11/imm32/alloc-id:fake:payload
25960     # "max"
25961     0x3/imm32/size
25962     0x6d/m 0x61/a 0x78/x
25963 _string-min:
25964     0x11/imm32/alloc-id:fake:payload
25965     # "min"
25966     0x3/imm32/size
25967     0x6d/m 0x69/i 0x6e/n
25968 _string-reciprocal:
25969     0x11/imm32/alloc-id:fake:payload
25970     # "reciprocal"
25971     0xa/imm32/size
25972     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
25973 _string-square-root:
25974     0x11/imm32/alloc-id:fake:payload
25975     # "square-root"
25976     0xb/imm32/size
25977     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
25978 _string-inverse-square-root:
25979     0x11/imm32/alloc-id:fake:payload
25980     # "inverse-square-root"
25981     0x13/imm32/size
25982     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
25983 _string-negate:  # (payload array byte)
25984     0x11/imm32/alloc-id:fake:payload
25985     # "negate"
25986     0x6/imm32/size
25987     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
25988 _string-or:  # (payload array byte)
25989     0x11/imm32/alloc-id:fake:payload
25990     # "or"
25991     0x2/imm32/size
25992     0x6f/o 0x72/r
25993 _string-or-with:  # (payload array byte)
25994     0x11/imm32/alloc-id:fake:payload
25995     # "or-with"
25996     0x7/imm32/size
25997     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
25998 _string-subtract:  # (payload array byte)
25999     0x11/imm32/alloc-id:fake:payload
26000     # "subtract"
26001     0x8/imm32/size
26002     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
26003 _string-subtract-from:  # (payload array byte)
26004     0x11/imm32/alloc-id:fake:payload
26005     # "subtract-from"
26006     0xd/imm32/size
26007     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
26008 _string-xor:  # (payload array byte)
26009     0x11/imm32/alloc-id:fake:payload
26010     # "xor"
26011     0x3/imm32/size
26012     0x78/x 0x6f/o 0x72/r
26013 _string-xor-with:  # (payload array byte)
26014     0x11/imm32/alloc-id:fake:payload
26015     # "xor-with"
26016     0x8/imm32/size
26017     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
26018 _string-shift-left:  # (payload array byte)
26019     0x11/imm32/alloc-id:fake:payload
26020     # "shift-left"
26021     0xa/imm32/size
26022     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
26023 _string-shift-right:  # (payload array byte)
26024     0x11/imm32/alloc-id:fake:payload
26025     # "shift-right"
26026     0xb/imm32/size
26027     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
26028 _string-shift-right-signed:  # (payload array byte)
26029     0x11/imm32/alloc-id:fake:payload
26030     # "shift-right-signed"
26031     0x12/imm32/size
26032     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
26033 
26034 # string literals for SubX instructions
26035 _string_01_add_to:  # (payload array byte)
26036     0x11/imm32/alloc-id:fake:payload
26037     # "01/add-to"
26038     0x9/imm32/size
26039     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
26040 _string_03_add:  # (payload array byte)
26041     0x11/imm32/alloc-id:fake:payload
26042     # "03/add"
26043     0x6/imm32/size
26044     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
26045 _string_05_add_to_eax:  # (payload array byte)
26046     0x11/imm32/alloc-id:fake:payload
26047     # "05/add-to-eax"
26048     0xd/imm32/size
26049     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
26050 _string_09_or_with:  # (payload array byte)
26051     0x11/imm32/alloc-id:fake:payload
26052     # "09/or-with"
26053     0xa/imm32/size
26054     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
26055 _string_0b_or:  # (payload array byte)
26056     0x11/imm32/alloc-id:fake:payload
26057     # "0b/or"
26058     0x5/imm32/size
26059     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
26060 _string_0d_or_with_eax:  # (payload array byte)
26061     0x11/imm32/alloc-id:fake:payload
26062     # "0d/or-with-eax"
26063     0xe/imm32/size
26064     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
26065 _string_0f_82_jump_label:  # (payload array byte)
26066     0x11/imm32/alloc-id:fake:payload
26067     # "0f 82/jump-if-addr<"
26068     0x13/imm32/size
26069     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/<
26070 _string_0f_82_jump_break:  # (payload array byte)
26071     0x11/imm32/alloc-id:fake:payload
26072     # "0f 82/jump-if-addr< break/disp32"
26073     0x20/imm32/size
26074     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
26075 _string_0f_82_jump_loop:  # (payload array byte)
26076     0x11/imm32/alloc-id:fake:payload
26077     # "0f 82/jump-if-addr< loop/disp32"
26078     0x1f/imm32/size
26079     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
26080 _string_0f_83_jump_label:  # (payload array byte)
26081     0x11/imm32/alloc-id:fake:payload
26082     # "0f 83/jump-if-addr>="
26083     0x14/imm32/size
26084     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/=
26085 _string_0f_83_jump_break:  # (payload array byte)
26086     0x11/imm32/alloc-id:fake:payload
26087     # "0f 83/jump-if-addr>= break/disp32"
26088     0x21/imm32/size
26089     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
26090 _string_0f_83_jump_loop:  # (payload array byte)
26091     0x11/imm32/alloc-id:fake:payload
26092     # "0f 83/jump-if-addr>= loop/disp32"
26093     0x20/imm32/size
26094     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
26095 _string_0f_84_jump_label:  # (payload array byte)
26096     0x11/imm32/alloc-id:fake:payload
26097     # "0f 84/jump-if-="
26098     0xf/imm32/size
26099     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/=
26100 _string_0f_84_jump_break:  # (payload array byte)
26101     0x11/imm32/alloc-id:fake:payload
26102     # "0f 84/jump-if-= break/disp32"
26103     0x1c/imm32/size
26104     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
26105 _string_0f_84_jump_loop:  # (payload array byte)
26106     0x11/imm32/alloc-id:fake:payload
26107     # "0f 84/jump-if-= loop/disp32"
26108     0x1b/imm32/size
26109     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
26110 _string_0f_85_jump_label:  # (payload array byte)
26111     0x11/imm32/alloc-id:fake:payload
26112     # "0f 85/jump-if-!="
26113     0x10/imm32/size
26114     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/=
26115 _string_0f_85_jump_break:  # (payload array byte)
26116     0x11/imm32/alloc-id:fake:payload
26117     # "0f 85/jump-if-!= break/disp32"
26118     0x1d/imm32/size
26119     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
26120 _string_0f_85_jump_loop:  # (payload array byte)
26121     0x11/imm32/alloc-id:fake:payload
26122     # "0f 85/jump-if-!= loop/disp32"
26123     0x1c/imm32/size
26124     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
26125 _string_0f_86_jump_label:  # (payload array byte)
26126     0x11/imm32/alloc-id:fake:payload
26127     # "0f 86/jump-if-addr<="
26128     0x14/imm32/size
26129     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/=
26130 _string_0f_86_jump_break:  # (payload array byte)
26131     0x11/imm32/alloc-id:fake:payload
26132     # "0f 86/jump-if-addr<= break/disp32"
26133     0x21/imm32/size
26134     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
26135 _string_0f_86_jump_loop:  # (payload array byte)
26136     0x11/imm32/alloc-id:fake:payload
26137     # "0f 86/jump-if-addr<= loop/disp32"
26138     0x20/imm32/size
26139     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
26140 _string_0f_87_jump_label:  # (payload array byte)
26141     0x11/imm32/alloc-id:fake:payload
26142     # "0f 87/jump-if-addr>"
26143     0x13/imm32/size
26144     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/>
26145 _string_0f_87_jump_break:  # (payload array byte)
26146     0x11/imm32/alloc-id:fake:payload
26147     # "0f 87/jump-if-addr> break/disp32"
26148     0x20/imm32/size
26149     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
26150 _string_0f_87_jump_loop:  # (payload array byte)
26151     0x11/imm32/alloc-id:fake:payload
26152     # "0f 87/jump-if-addr> loop/disp32"
26153     0x1f/imm32/size
26154     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
26155 _string_0f_8c_jump_label:  # (payload array byte)
26156     0x11/imm32/alloc-id:fake:payload
26157     # "0f 8c/jump-if-<"
26158     0xf/imm32/size
26159     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/<
26160 _string_0f_8c_jump_break:  # (payload array byte)
26161     0x11/imm32/alloc-id:fake:payload
26162     # "0f 8c/jump-if-< break/disp32"
26163     0x1c/imm32/size
26164     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
26165 _string_0f_8c_jump_loop:  # (payload array byte)
26166     0x11/imm32/alloc-id:fake:payload
26167     # "0f 8c/jump-if-< loop/disp32"
26168     0x1b/imm32/size
26169     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
26170 _string_0f_8d_jump_label:  # (payload array byte)
26171     0x11/imm32/alloc-id:fake:payload
26172     # "0f 8d/jump-if->="
26173     0x10/imm32/size
26174     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/=
26175 _string_0f_8d_jump_break:  # (payload array byte)
26176     0x11/imm32/alloc-id:fake:payload
26177     # "0f 8d/jump-if->= break/disp32"
26178     0x1d/imm32/size
26179     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
26180 _string_0f_8d_jump_loop:  # (payload array byte)
26181     0x11/imm32/alloc-id:fake:payload
26182     # "0f 8d/jump-if->= loop/disp32"
26183     0x1c/imm32/size
26184     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
26185 _string_0f_8e_jump_label:  # (payload array byte)
26186     0x11/imm32/alloc-id:fake:payload
26187     # "0f 8e/jump-if-<="
26188     0x10/imm32/size
26189     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/=
26190 _string_0f_8e_jump_break:  # (payload array byte)
26191     0x11/imm32/alloc-id:fake:payload
26192     # "0f 8e/jump-if-<= break/disp32"
26193     0x1d/imm32/size
26194     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
26195 _string_0f_8e_jump_loop:  # (payload array byte)
26196     0x11/imm32/alloc-id:fake:payload
26197     # "0f 8e/jump-if-<= loop/disp32"
26198     0x1c/imm32/size
26199     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
26200 _string_0f_8f_jump_label:  # (payload array byte)
26201     0x11/imm32/alloc-id:fake:payload
26202     # "0f 8f/jump-if->"
26203     0xf/imm32/size
26204     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/>
26205 _string_0f_8f_jump_break:  # (payload array byte)
26206     0x11/imm32/alloc-id:fake:payload
26207     # "0f 8f/jump-if-> break/disp32"
26208     0x1c/imm32/size
26209     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
26210 _string_0f_8f_jump_loop:  # (payload array byte)
26211     0x11/imm32/alloc-id:fake:payload
26212     # "0f 8f/jump-if-> loop/disp32"
26213     0x1b/imm32/size
26214     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
26215 _string_0f_af_multiply:  # (payload array byte)
26216     0x11/imm32/alloc-id:fake:payload
26217     # "0f af/multiply"
26218     0xe/imm32/size
26219     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
26220 _string_f3_0f_2a_convert_to_float:
26221     0x11/imm32/alloc-id:fake:payload
26222     # "f3 0f 2a/convert-to-float"
26223     0x19/imm32/size
26224     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
26225 _string_f3_0f_2d_convert_to_int:
26226     0x11/imm32/alloc-id:fake:payload
26227     # "f3 0f 2d/convert-to-int"
26228     0x17/imm32/size
26229     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
26230 _string_f3_0f_2c_truncate_to_int:
26231     0x11/imm32/alloc-id:fake:payload
26232     # "f3 0f 2c/truncate-to-int"
26233     0x18/imm32/size
26234     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
26235 _string_f3_0f_58_add:
26236     0x11/imm32/alloc-id:fake:payload
26237     # "f3 0f 58/add"
26238     0xc/imm32/size
26239     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
26240 _string_f3_0f_5c_subtract:
26241     0x11/imm32/alloc-id:fake:payload
26242     # "f3 0f 5c/subtract"
26243     0x11/imm32/size
26244     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
26245 _string_f3_0f_59_multiply:
26246     0x11/imm32/alloc-id:fake:payload
26247     # "f3 0f 59/multiply"
26248     0x11/imm32/size
26249     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
26250 _string_f3_0f_5e_divide:
26251     0x11/imm32/alloc-id:fake:payload
26252     # "f3 0f 5e/divide"
26253     0xf/imm32/size
26254     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
26255 _string_f3_0f_53_reciprocal:
26256     0x11/imm32/alloc-id:fake:payload
26257     # "f3 0f 53/reciprocal"
26258     0x13/imm32/size
26259     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
26260 _string_f3_0f_51_square_root:
26261     0x11/imm32/alloc-id:fake:payload
26262     # "f3 0f 51/square-root"
26263     0x14/imm32/size
26264     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
26265 _string_f3_0f_52_inverse_square_root:
26266     0x11/imm32/alloc-id:fake:payload
26267     # "f3 0f 52/inverse-square-root"
26268     0x1c/imm32/size
26269     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
26270 _string_f3_0f_5d_min:
26271     0x11/imm32/alloc-id:fake:payload
26272     # "f3 0f 5d/min"
26273     0xc/imm32/size
26274     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
26275 _string_f3_0f_5f_max:
26276     0x11/imm32/alloc-id:fake:payload
26277     # "f3 0f 5f/max"
26278     0xc/imm32/size
26279     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
26280 _string_f3_0f_10_copy:
26281     0x11/imm32/alloc-id:fake:payload
26282     # "f3 0f 10/copy"
26283     0xd/imm32/size
26284     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
26285 _string_f3_0f_11_copy:
26286     0x11/imm32/alloc-id:fake:payload
26287     # "f3 0f 11/copy"
26288     0xd/imm32/size
26289     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
26290 _string_0f_2f_compare:
26291     0x11/imm32/alloc-id:fake:payload
26292     # "0f 2f/compare"
26293     0xd/imm32/size
26294     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
26295 _string_21_and_with:  # (payload array byte)
26296     0x11/imm32/alloc-id:fake:payload
26297     # "21/and-with"
26298     0xb/imm32/size
26299     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
26300 _string_23_and:  # (payload array byte)
26301     0x11/imm32/alloc-id:fake:payload
26302     # "23/and"
26303     0x6/imm32/size
26304     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
26305 _string_25_and_with_eax:  # (payload array byte)
26306     0x11/imm32/alloc-id:fake:payload
26307     # "25/and-with-eax"
26308     0xf/imm32/size
26309     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
26310 _string_29_subtract_from:  # (payload array byte)
26311     0x11/imm32/alloc-id:fake:payload
26312     # "29/subtract-from"
26313     0x10/imm32/size
26314     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
26315 _string_2b_subtract:  # (payload array byte)
26316     0x11/imm32/alloc-id:fake:payload
26317     # "2b/subtract"
26318     0xb/imm32/size
26319     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
26320 _string_2d_subtract_from_eax:  # (payload array byte)
26321     0x11/imm32/alloc-id:fake:payload
26322     # "2d/subtract-from-eax"
26323     0x14/imm32/size
26324     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
26325 _string_31_xor_with:  # (payload array byte)
26326     0x11/imm32/alloc-id:fake:payload
26327     # "31/xor-with"
26328     0xb/imm32/size
26329     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
26330 _string_33_xor:  # (payload array byte)
26331     0x11/imm32/alloc-id:fake:payload
26332     # "33/xor"
26333     0x6/imm32/size
26334     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
26335 _string_35_xor_with_eax:  # (payload array byte)
26336     0x11/imm32/alloc-id:fake:payload
26337     # "35/xor-with-eax"
26338     0xf/imm32/size
26339     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
26340 _string_39_compare->:  # (payload array byte)
26341     0x11/imm32/alloc-id:fake:payload
26342     # "39/compare->"
26343     0xc/imm32/size
26344     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
26345 _string_3b_compare<-:  # (payload array byte)
26346     0x11/imm32/alloc-id:fake:payload
26347     # "3b/compare<-"
26348     0xc/imm32/size
26349     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
26350 _string_3d_compare_eax_with:  # (payload array byte)
26351     0x11/imm32/alloc-id:fake:payload
26352     # "3d/compare-eax-with"
26353     0x13/imm32/size
26354     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
26355 _string_40_increment_eax:  # (payload array byte)
26356     0x11/imm32/alloc-id:fake:payload
26357     # "40/increment-eax"
26358     0x10/imm32/size
26359     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
26360 _string_41_increment_ecx:  # (payload array byte)
26361     0x11/imm32/alloc-id:fake:payload
26362     # "41/increment-ecx"
26363     0x10/imm32/size
26364     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
26365 _string_42_increment_edx:  # (payload array byte)
26366     0x11/imm32/alloc-id:fake:payload
26367     # "42/increment-edx"
26368     0x10/imm32/size
26369     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
26370 _string_43_increment_ebx:  # (payload array byte)
26371     0x11/imm32/alloc-id:fake:payload
26372     # "43/increment-ebx"
26373     0x10/imm32/size
26374     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
26375 _string_46_increment_esi:  # (payload array byte)
26376     0x11/imm32/alloc-id:fake:payload
26377     # "46/increment-esi"
26378     0x10/imm32/size
26379     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
26380 _string_47_increment_edi:  # (payload array byte)
26381     0x11/imm32/alloc-id:fake:payload
26382     # "47/increment-edi"
26383     0x10/imm32/size
26384     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
26385 _string_48_decrement_eax:  # (payload array byte)
26386     0x11/imm32/alloc-id:fake:payload
26387     # "48/decrement-eax"
26388     0x10/imm32/size
26389     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
26390 _string_49_decrement_ecx:  # (payload array byte)
26391     0x11/imm32/alloc-id:fake:payload
26392     # "49/decrement-ecx"
26393     0x10/imm32/size
26394     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
26395 _string_4a_decrement_edx:  # (payload array byte)
26396     0x11/imm32/alloc-id:fake:payload
26397     # "4a/decrement-edx"
26398     0x10/imm32/size
26399     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
26400 _string_4b_decrement_ebx:  # (payload array byte)
26401     0x11/imm32/alloc-id:fake:payload
26402     # "4b/decrement-ebx"
26403     0x10/imm32/size
26404     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
26405 _string_4e_decrement_esi:  # (payload array byte)
26406     0x11/imm32/alloc-id:fake:payload
26407     # "4e/decrement-esi"
26408     0x10/imm32/size
26409     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
26410 _string_4f_decrement_edi:  # (payload array byte)
26411     0x11/imm32/alloc-id:fake:payload
26412     # "4f/decrement-edi"
26413     0x10/imm32/size
26414     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
26415 _string_81_subop_add:  # (payload array byte)
26416     0x11/imm32/alloc-id:fake:payload
26417     # "81 0/subop/add"
26418     0xe/imm32/size
26419     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
26420 _string_81_subop_or:  # (payload array byte)
26421     0x11/imm32/alloc-id:fake:payload
26422     # "81 1/subop/or"
26423     0xd/imm32/size
26424     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
26425 _string_81_subop_and:  # (payload array byte)
26426     0x11/imm32/alloc-id:fake:payload
26427     # "81 4/subop/and"
26428     0xe/imm32/size
26429     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
26430 _string_81_subop_subtract:  # (payload array byte)
26431     0x11/imm32/alloc-id:fake:payload
26432     # "81 5/subop/subtract"
26433     0x13/imm32/size
26434     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
26435 _string_81_subop_xor:  # (payload array byte)
26436     0x11/imm32/alloc-id:fake:payload
26437     # "81 6/subop/xor"
26438     0xe/imm32/size
26439     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
26440 _string_81_subop_compare:  # (payload array byte)
26441     0x11/imm32/alloc-id:fake:payload
26442     # "81 7/subop/compare"
26443     0x12/imm32/size
26444     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
26445 _string_89_<-:  # (payload array byte)
26446     0x11/imm32/alloc-id:fake:payload
26447     # "89/<-"
26448     0x5/imm32/size
26449     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
26450 _string_8b_->:  # (payload array byte)
26451     0x11/imm32/alloc-id:fake:payload
26452     # "8b/->"
26453     0x5/imm32/size
26454     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
26455 _string_8a_copy_byte:
26456     0x11/imm32/alloc-id:fake:payload
26457     # "8a/byte->"
26458     0x9/imm32/size
26459     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
26460 _string_88_copy_byte:
26461     0x11/imm32/alloc-id:fake:payload
26462     # "88/byte<-"
26463     0x9/imm32/size
26464     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
26465 _string_8d_copy_address:  # (payload array byte)
26466     0x11/imm32/alloc-id:fake:payload
26467     # "8d/copy-address"
26468     0xf/imm32/size
26469     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
26470 _string_b8_copy_to_eax:  # (payload array byte)
26471     0x11/imm32/alloc-id:fake:payload
26472     # "b8/copy-to-eax"
26473     0xe/imm32/size
26474     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
26475 _string_b9_copy_to_ecx:  # (payload array byte)
26476     0x11/imm32/alloc-id:fake:payload
26477     # "b9/copy-to-ecx"
26478     0xe/imm32/size
26479     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
26480 _string_ba_copy_to_edx:  # (payload array byte)
26481     0x11/imm32/alloc-id:fake:payload
26482     # "ba/copy-to-edx"
26483     0xe/imm32/size
26484     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
26485 _string_bb_copy_to_ebx:  # (payload array byte)
26486     0x11/imm32/alloc-id:fake:payload
26487     # "bb/copy-to-ebx"
26488     0xe/imm32/size
26489     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
26490 _string_be_copy_to_esi:  # (payload array byte)
26491     0x11/imm32/alloc-id:fake:payload
26492     # "be/copy-to-esi"
26493     0xe/imm32/size
26494     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
26495 _string_bf_copy_to_edi:  # (payload array byte)
26496     0x11/imm32/alloc-id:fake:payload
26497     # "bf/copy-to-edi"
26498     0xe/imm32/size
26499     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
26500 _string_c7_subop_copy:  # (payload array byte)
26501     0x11/imm32/alloc-id:fake:payload
26502     # "c7 0/subop/copy"
26503     0xf/imm32/size
26504     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
26505 _string_e9_jump_label:  # (payload array byte)
26506     0x11/imm32/alloc-id:fake:payload
26507     # "e9/jump"
26508     0x7/imm32/size
26509     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
26510 _string_e9_jump_break:  # (payload array byte)
26511     0x11/imm32/alloc-id:fake:payload
26512     # "e9/jump break/disp32"
26513     0x14/imm32/size
26514     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
26515 _string_e9_jump_loop:  # (payload array byte)
26516     0x11/imm32/alloc-id:fake:payload
26517     # "e9/jump loop/disp32"
26518     0x13/imm32/size
26519     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
26520 _string_f7_subop_negate:
26521     0x11/imm32/alloc-id:fake:payload
26522     # "f7 3/subop/negate"
26523     0x11/imm32/size
26524     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
26525 _string_ff_subop_increment:  # (payload array byte)
26526     0x11/imm32/alloc-id:fake:payload
26527     # "ff 0/subop/increment"
26528     0x14/imm32/size
26529     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
26530 _string_ff_subop_decrement:  # (payload array byte)
26531     0x11/imm32/alloc-id:fake:payload
26532     # "ff 1/subop/decrement"
26533     0x14/imm32/size
26534     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
26535 _string_c1_subop_shift_left:  # (payload array byte)
26536     0x11/imm32/alloc-id:fake:payload
26537     # "c1/shift 4/subop/left"
26538     0x15/imm32/size
26539     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
26540 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
26541     0x11/imm32/alloc-id:fake:payload
26542     # "c1/shift 5/subop/right-padding-zeroes"
26543     0x25/imm32/size
26544     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
26545 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
26546     0x11/imm32/alloc-id:fake:payload
26547     # "c1/shift 7/subop/right-preserving-sign"
26548     0x26/imm32/size
26549     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
26550 
26551 Single-int-var-in-mem:  # (payload list var)
26552     0x11/imm32/alloc-id:fake:payload
26553     0x11/imm32/alloc-id:fake
26554     Int-var-in-mem/imm32
26555     0/imm32/next
26556     0/imm32/next
26557 
26558 Int-var-in-mem:  # (payload var)
26559     0x11/imm32/alloc-id:fake:payload
26560     0/imm32/name
26561     0/imm32/name
26562     0x11/imm32/alloc-id:fake
26563     Type-int/imm32
26564     1/imm32/some-block-depth
26565     1/imm32/some-stack-offset
26566     0/imm32/no-register
26567     0/imm32/no-register
26568 
26569 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
26570 Single-byte-var-in-mem:  # (payload list var)
26571     0x11/imm32/alloc-id:fake:payload
26572     0x11/imm32/alloc-id:fake
26573     Byte-var-in-mem/imm32
26574     0/imm32/next
26575     0/imm32/next
26576 
26577 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
26578 Byte-var-in-mem:  # (payload var)
26579     0x11/imm32/alloc-id:fake:payload
26580     0/imm32/name
26581     0/imm32/name
26582     0x11/imm32/alloc-id:fake
26583     Type-byte/imm32
26584     1/imm32/some-block-depth
26585     1/imm32/some-stack-offset
26586     0/imm32/no-register
26587     0/imm32/no-register
26588 
26589 Two-args-int-stack-int-reg:  # (payload list var)
26590     0x11/imm32/alloc-id:fake:payload
26591     0x11/imm32/alloc-id:fake
26592     Int-var-in-mem/imm32
26593     0x11/imm32/alloc-id:fake
26594     Single-int-var-in-some-register/imm32/next
26595 
26596 Two-int-args-in-regs:  # (payload list var)
26597     0x11/imm32/alloc-id:fake:payload
26598     0x11/imm32/alloc-id:fake
26599     Int-var-in-some-register/imm32
26600     0x11/imm32/alloc-id:fake
26601     Single-int-var-in-some-register/imm32/next
26602 
26603 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
26604 Two-args-byte-stack-byte-reg:  # (payload list var)
26605     0x11/imm32/alloc-id:fake:payload
26606     0x11/imm32/alloc-id:fake
26607     Byte-var-in-mem/imm32
26608     0x11/imm32/alloc-id:fake
26609     Single-byte-var-in-some-register/imm32/next
26610 
26611 Two-args-int-reg-int-stack:  # (payload list var)
26612     0x11/imm32/alloc-id:fake:payload
26613     0x11/imm32/alloc-id:fake
26614     Int-var-in-some-register/imm32
26615     0x11/imm32/alloc-id:fake
26616     Single-int-var-in-mem/imm32/next
26617 
26618 Two-args-int-eax-int-literal:  # (payload list var)
26619     0x11/imm32/alloc-id:fake:payload
26620     0x11/imm32/alloc-id:fake
26621     Int-var-in-eax/imm32
26622     0x11/imm32/alloc-id:fake
26623     Single-lit-var/imm32/next
26624 
26625 Int-var-and-literal:  # (payload list var)
26626     0x11/imm32/alloc-id:fake:payload
26627     0x11/imm32/alloc-id:fake
26628     Int-var-in-mem/imm32
26629     0x11/imm32/alloc-id:fake
26630     Single-lit-var/imm32/next
26631 
26632 Int-var-in-register-and-literal:  # (payload list var)
26633     0x11/imm32/alloc-id:fake:payload
26634     0x11/imm32/alloc-id:fake
26635     Int-var-in-some-register/imm32
26636     0x11/imm32/alloc-id:fake
26637     Single-lit-var/imm32/next
26638 
26639 Two-float-args-in-regs:  # (payload list var)
26640     0x11/imm32/alloc-id:fake:payload
26641     0x11/imm32/alloc-id:fake
26642     Float-var-in-some-register/imm32
26643     0x11/imm32/alloc-id:fake
26644     Single-float-var-in-some-register/imm32/next
26645 
26646 Two-args-float-reg-float-stack:  # (payload list var)
26647     0x11/imm32/alloc-id:fake:payload
26648     0x11/imm32/alloc-id:fake
26649     Float-var-in-some-register/imm32
26650     0x11/imm32/alloc-id:fake
26651     Single-float-var-in-mem/imm32/next
26652 
26653 Two-args-float-stack-float-reg:  # (payload list var)
26654     0x11/imm32/alloc-id:fake:payload
26655     0x11/imm32/alloc-id:fake
26656     Float-var-in-mem/imm32
26657     0x11/imm32/alloc-id:fake
26658     Single-float-var-in-some-register/imm32/next
26659 
26660 Single-int-var-in-some-register:  # (payload list var)
26661     0x11/imm32/alloc-id:fake:payload
26662     0x11/imm32/alloc-id:fake
26663     Int-var-in-some-register/imm32
26664     0/imm32/next
26665     0/imm32/next
26666 
26667 Single-addr-var-in-some-register:  # (payload list var)
26668     0x11/imm32/alloc-id:fake:payload
26669     0x11/imm32/alloc-id:fake
26670     Addr-var-in-some-register/imm32
26671     0/imm32/next
26672     0/imm32/next
26673 
26674 Single-byte-var-in-some-register:  # (payload list var)
26675     0x11/imm32/alloc-id:fake:payload
26676     0x11/imm32/alloc-id:fake
26677     Byte-var-in-some-register/imm32
26678     0/imm32/next
26679     0/imm32/next
26680 
26681 Int-var-in-some-register:  # (payload var)
26682     0x11/imm32/alloc-id:fake:payload
26683     0/imm32/name
26684     0/imm32/name
26685     0x11/imm32/alloc-id:fake
26686     Type-int/imm32
26687     1/imm32/some-block-depth
26688     0/imm32/no-stack-offset
26689     0x11/imm32/alloc-id:fake
26690     Any-register/imm32
26691 
26692 Any-register:  # (payload array byte)
26693     0x11/imm32/alloc-id:fake:payload
26694     1/imm32/size
26695     # data
26696     2a/asterisk
26697 
26698 Addr-var-in-some-register:  # (payload var)
26699     0x11/imm32/alloc-id:fake:payload
26700     0/imm32/name
26701     0/imm32/name
26702     0x11/imm32/alloc-id:fake
26703     Type-addr/imm32
26704     1/imm32/some-block-depth
26705     0/imm32/no-stack-offset
26706     0x11/imm32/alloc-id:fake
26707     Any-register/imm32
26708 
26709 Byte-var-in-some-register:  # (payload var)
26710     0x11/imm32/alloc-id:fake:payload
26711     0/imm32/name
26712     0/imm32/name
26713     0x11/imm32/alloc-id:fake
26714     Type-byte/imm32
26715     1/imm32/some-block-depth
26716     0/imm32/no-stack-offset
26717     0x11/imm32/alloc-id:fake
26718     Any-register/imm32
26719 
26720 Single-int-var-in-eax:  # (payload list var)
26721     0x11/imm32/alloc-id:fake:payload
26722     0x11/imm32/alloc-id:fake
26723     Int-var-in-eax/imm32
26724     0/imm32/next
26725     0/imm32/next
26726 
26727 Int-var-in-eax:
26728     0x11/imm32/alloc-id:fake:payload
26729     0/imm32/name
26730     0/imm32/name
26731     0x11/imm32/alloc-id:fake
26732     Type-int/imm32
26733     1/imm32/some-block-depth
26734     0/imm32/no-stack-offset
26735     0x11/imm32/alloc-id:fake
26736     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
26737 
26738 Single-int-var-in-ecx:  # (payload list var)
26739     0x11/imm32/alloc-id:fake:payload
26740     0x11/imm32/alloc-id:fake
26741     Int-var-in-ecx/imm32
26742     0/imm32/next
26743     0/imm32/next
26744 
26745 Int-var-in-ecx:
26746     0x11/imm32/alloc-id:fake:payload
26747     0/imm32/name
26748     0/imm32/name
26749     0x11/imm32/alloc-id:fake
26750     Type-int/imm32
26751     1/imm32/some-block-depth
26752     0/imm32/no-stack-offset
26753     0x11/imm32/alloc-id:fake
26754     $Register-ecx/imm32/register
26755 
26756 Single-int-var-in-edx:  # (payload list var)
26757     0x11/imm32/alloc-id:fake:payload
26758     0x11/imm32/alloc-id:fake
26759     Int-var-in-edx/imm32
26760     0/imm32/next
26761     0/imm32/next
26762 
26763 Int-var-in-edx:  # (payload list var)
26764     0x11/imm32/alloc-id:fake:payload
26765     0/imm32/name
26766     0/imm32/name
26767     0x11/imm32/alloc-id:fake
26768     Type-int/imm32
26769     1/imm32/some-block-depth
26770     0/imm32/no-stack-offset
26771     0x11/imm32/alloc-id:fake
26772     $Register-edx/imm32/register
26773 
26774 Single-int-var-in-ebx:  # (payload list var)
26775     0x11/imm32/alloc-id:fake:payload
26776     0x11/imm32/alloc-id:fake
26777     Int-var-in-ebx/imm32
26778     0/imm32/next
26779     0/imm32/next
26780 
26781 Int-var-in-ebx:  # (payload list var)
26782     0x11/imm32/alloc-id:fake:payload
26783     0/imm32/name
26784     0/imm32/name
26785     0x11/imm32/alloc-id:fake
26786     Type-int/imm32
26787     1/imm32/some-block-depth
26788     0/imm32/no-stack-offset
26789     0x11/imm32/alloc-id:fake
26790     $Register-ebx/imm32/register
26791 
26792 Single-int-var-in-esi:  # (payload list var)
26793     0x11/imm32/alloc-id:fake:payload
26794     0x11/imm32/alloc-id:fake
26795     Int-var-in-esi/imm32
26796     0/imm32/next
26797     0/imm32/next
26798 
26799 Int-var-in-esi:  # (payload list var)
26800     0x11/imm32/alloc-id:fake:payload
26801     0/imm32/name
26802     0/imm32/name
26803     0x11/imm32/alloc-id:fake
26804     Type-int/imm32
26805     1/imm32/some-block-depth
26806     0/imm32/no-stack-offset
26807     0x11/imm32/alloc-id:fake
26808     $Register-esi/imm32/register
26809 
26810 Single-int-var-in-edi:  # (payload list var)
26811     0x11/imm32/alloc-id:fake:payload
26812     0x11/imm32/alloc-id:fake
26813     Int-var-in-edi/imm32
26814     0/imm32/next
26815     0/imm32/next
26816 
26817 Int-var-in-edi:  # (payload list var)
26818     0x11/imm32/alloc-id:fake:payload
26819     0/imm32/name
26820     0/imm32/name
26821     0x11/imm32/alloc-id:fake
26822     Type-int/imm32
26823     1/imm32/some-block-depth
26824     0/imm32/no-stack-offset
26825     0x11/imm32/alloc-id:fake
26826     $Register-edi/imm32/register
26827 
26828 Single-lit-var:  # (payload list var)
26829     0x11/imm32/alloc-id:fake:payload
26830     0x11/imm32/alloc-id:fake
26831     Lit-var/imm32
26832     0/imm32/next
26833     0/imm32/next
26834 
26835 Lit-var:  # (payload var)
26836     0x11/imm32/alloc-id:fake:payload
26837     0/imm32/name
26838     0/imm32/name
26839     0x11/imm32/alloc-id:fake
26840     Type-literal/imm32
26841     1/imm32/some-block-depth
26842     0/imm32/no-stack-offset
26843     0/imm32/no-register
26844     0/imm32/no-register
26845 
26846 Single-float-var-in-mem:  # (payload list var)
26847     0x11/imm32/alloc-id:fake:payload
26848     0x11/imm32/alloc-id:fake
26849     Float-var-in-mem/imm32
26850     0/imm32/next
26851     0/imm32/next
26852 
26853 Float-var-in-mem:  # (payload var)
26854     0x11/imm32/alloc-id:fake:payload
26855     0/imm32/name
26856     0/imm32/name
26857     0x11/imm32/alloc-id:fake
26858     Type-float/imm32
26859     1/imm32/some-block-depth
26860     1/imm32/some-stack-offset
26861     0/imm32/no-register
26862     0/imm32/no-register
26863 
26864 Single-float-var-in-some-register:  # (payload list var)
26865     0x11/imm32/alloc-id:fake:payload
26866     0x11/imm32/alloc-id:fake
26867     Float-var-in-some-register/imm32
26868     0/imm32/next
26869     0/imm32/next
26870 
26871 Float-var-in-some-register:  # (payload var)
26872     0x11/imm32/alloc-id:fake:payload
26873     0/imm32/name
26874     0/imm32/name
26875     0x11/imm32/alloc-id:fake
26876     Type-float/imm32
26877     1/imm32/some-block-depth
26878     0/imm32/no-stack-offset
26879     0x11/imm32/alloc-id:fake
26880     Any-register/imm32
26881 
26882 Type-int:  # (payload type-tree)
26883     0x11/imm32/alloc-id:fake:payload
26884     1/imm32/is-atom
26885     1/imm32/value:int
26886     0/imm32/left:unused
26887     0/imm32/right:null
26888     0/imm32/right:null
26889 
26890 Type-literal:  # (payload type-tree)
26891     0x11/imm32/alloc-id:fake:payload
26892     1/imm32/is-atom
26893     0/imm32/value:literal
26894     0/imm32/left:unused
26895     0/imm32/right:null
26896     0/imm32/right:null
26897 
26898 Type-addr:  # (payload type-tree)
26899     0x11/imm32/alloc-id:fake:payload
26900     1/imm32/is-atom
26901     2/imm32/value:addr
26902     0/imm32/left:unused
26903     0/imm32/right:null
26904     0/imm32/right:null
26905 
26906 Type-byte:  # (payload type-tree)
26907     0x11/imm32/alloc-id:fake:payload
26908     1/imm32/is-atom
26909     8/imm32/value:byte
26910     0/imm32/left:unused
26911     0/imm32/right:null
26912     0/imm32/right:null
26913 
26914 Type-float:  # (payload type-tree)
26915     0x11/imm32/alloc-id:fake:payload
26916     1/imm32/is-atom
26917     0xf/imm32/value:float
26918     0/imm32/left:unused
26919     0/imm32/right:null
26920     0/imm32/right:null
26921 
26922 == code
26923 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
26924     # . prologue
26925     55/push-ebp
26926     89/<- %ebp 4/r32/esp
26927     # . save registers
26928     50/push-eax
26929     51/push-ecx
26930     # ecx = primitive
26931     8b/-> *(ebp+0x10) 1/r32/ecx
26932     # emit primitive name
26933     (emit-indent *(ebp+8) *Curr-block-depth)
26934     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
26935     (write-buffered *(ebp+8) %eax)
26936     # emit rm32 if necessary
26937     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
26938     # emit xm32 if necessary
26939     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
26940     # emit r32 if necessary
26941     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
26942     # emit x32 if necessary
26943     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
26944     # emit imm32 if necessary
26945     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
26946     # emit imm8 if necessary
26947     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
26948     # emit disp32 if necessary
26949     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
26950     (write-buffered *(ebp+8) Newline)
26951 $emit-subx-primitive:end:
26952     # . restore registers
26953     59/pop-to-ecx
26954     58/pop-to-eax
26955     # . epilogue
26956     89/<- %esp 5/r32/ebp
26957     5d/pop-to-ebp
26958     c3/return
26959 
26960 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26961     # . prologue
26962     55/push-ebp
26963     89/<- %ebp 4/r32/esp
26964     # . save registers
26965     50/push-eax
26966     # if (l == 0) return
26967     81 7/subop/compare *(ebp+0xc) 0/imm32
26968     74/jump-if-= $emit-subx-rm32:end/disp8
26969     # var v/eax: (addr stmt-var)
26970     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
26971     (emit-subx-var-as-rm32 *(ebp+8) %eax)
26972 $emit-subx-rm32:end:
26973     # . restore registers
26974     58/pop-to-eax
26975     # . epilogue
26976     89/<- %esp 5/r32/ebp
26977     5d/pop-to-ebp
26978     c3/return
26979 
26980 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)
26981     # . prologue
26982     55/push-ebp
26983     89/<- %ebp 4/r32/esp
26984     # . save registers
26985     51/push-ecx
26986     # eax = l
26987     8b/-> *(ebp+0xc) 0/r32/eax
26988     # ecx = stmt
26989     8b/-> *(ebp+8) 1/r32/ecx
26990     # if (l == 1) return stmt->inouts
26991     {
26992       3d/compare-eax-and 1/imm32
26993       75/jump-if-!= break/disp8
26994 $get-stmt-operand-from-arg-location:1:
26995       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26996       eb/jump $get-stmt-operand-from-arg-location:end/disp8
26997     }
26998     # if (l == 2) return stmt->inouts->next
26999     {
27000       3d/compare-eax-and 2/imm32
27001       75/jump-if-!= break/disp8
27002 $get-stmt-operand-from-arg-location:2:
27003       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27004       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27005       eb/jump $get-stmt-operand-from-arg-location:end/disp8
27006     }
27007     # if (l == 3) return stmt->outputs
27008     {
27009       3d/compare-eax-and 3/imm32
27010       75/jump-if-!= break/disp8
27011 $get-stmt-operand-from-arg-location:3:
27012       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27013       eb/jump $get-stmt-operand-from-arg-location:end/disp8
27014     }
27015     # abort
27016     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
27017 $get-stmt-operand-from-arg-location:end:
27018     # . restore registers
27019     59/pop-to-ecx
27020     # . epilogue
27021     89/<- %esp 5/r32/ebp
27022     5d/pop-to-ebp
27023     c3/return
27024 
27025 $get-stmt-operand-from-arg-location:abort:
27026     # error("invalid arg-location " eax)
27027     (write-buffered *(ebp+0x10) "invalid arg-location ")
27028     (write-int32-hex-buffered *(ebp+0x10) %eax)
27029     (write-buffered *(ebp+0x10) Newline)
27030     (flush *(ebp+0x10))
27031     (stop *(ebp+0x14) 1)
27032     # never gets here
27033 
27034 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
27035     # . prologue
27036     55/push-ebp
27037     89/<- %ebp 4/r32/esp
27038     # . save registers
27039     50/push-eax
27040     51/push-ecx
27041     # if (l == 0) return
27042     81 7/subop/compare *(ebp+0xc) 0/imm32
27043     0f 84/jump-if-= $emit-subx-r32:end/disp32
27044     # var v/eax: (addr stmt-var)
27045     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
27046     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27047     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27048 #?     (write-buffered Stderr "looking up ")
27049 #?     (write-buffered Stderr %eax)
27050 #?     (write-buffered Stderr Newline)
27051 #?     (flush Stderr)
27052     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
27053     (write-buffered *(ebp+8) Space)
27054     (write-int32-hex-buffered *(ebp+8) *eax)
27055     (write-buffered *(ebp+8) "/r32")
27056 $emit-subx-r32:end:
27057     # . restore registers
27058     59/pop-to-ecx
27059     58/pop-to-eax
27060     # . epilogue
27061     89/<- %esp 5/r32/ebp
27062     5d/pop-to-ebp
27063     c3/return
27064 
27065 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
27066     # . prologue
27067     55/push-ebp
27068     89/<- %ebp 4/r32/esp
27069     # . save registers
27070     50/push-eax
27071     51/push-ecx
27072     # if (l == 0) return
27073     81 7/subop/compare *(ebp+0xc) 0/imm32
27074     0f 84/jump-if-= $emit-subx-x32:end/disp32
27075     # var v/eax: (addr stmt-var)
27076     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
27077     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27078     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27079 #?     (write-buffered Stderr "looking up ")
27080 #?     (write-buffered Stderr %eax)
27081 #?     (write-buffered Stderr Newline)
27082 #?     (flush Stderr)
27083     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
27084     (write-buffered *(ebp+8) Space)
27085     (write-int32-hex-buffered *(ebp+8) *eax)
27086     (write-buffered *(ebp+8) "/x32")
27087 $emit-subx-x32:end:
27088     # . restore registers
27089     59/pop-to-ecx
27090     58/pop-to-eax
27091     # . epilogue
27092     89/<- %esp 5/r32/ebp
27093     5d/pop-to-ebp
27094     c3/return
27095 
27096 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
27097     # . prologue
27098     55/push-ebp
27099     89/<- %ebp 4/r32/esp
27100     # . save registers
27101     50/push-eax
27102     51/push-ecx
27103     # if (l == 0) return
27104     81 7/subop/compare *(ebp+0xc) 0/imm32
27105     0f 84/jump-if-= $emit-subx-imm32:end/disp32
27106     # var v/eax: (handle var)
27107     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
27108     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27109     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27110     (write-buffered *(ebp+8) Space)
27111     (write-buffered *(ebp+8) %eax)
27112     (write-buffered *(ebp+8) "/imm32")
27113 $emit-subx-imm32:end:
27114     # . restore registers
27115     59/pop-to-ecx
27116     58/pop-to-eax
27117     # . epilogue
27118     89/<- %esp 5/r32/ebp
27119     5d/pop-to-ebp
27120     c3/return
27121 
27122 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
27123     # . prologue
27124     55/push-ebp
27125     89/<- %ebp 4/r32/esp
27126     # . save registers
27127     50/push-eax
27128     51/push-ecx
27129     # if (l == 0) return
27130     81 7/subop/compare *(ebp+0xc) 0/imm32
27131     0f 84/jump-if-= $emit-subx-imm32:end/disp32
27132     # var v/eax: (handle var)
27133     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
27134     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27135     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27136     (write-buffered *(ebp+8) Space)
27137     (write-buffered *(ebp+8) %eax)
27138     (write-buffered *(ebp+8) "/imm8")
27139 $emit-subx-imm8:end:
27140     # . restore registers
27141     59/pop-to-ecx
27142     58/pop-to-eax
27143     # . epilogue
27144     89/<- %esp 5/r32/ebp
27145     5d/pop-to-ebp
27146     c3/return
27147 
27148 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27149     # . prologue
27150     55/push-ebp
27151     89/<- %ebp 4/r32/esp
27152     # . save registers
27153     50/push-eax
27154     51/push-ecx
27155     # if (location == 0) return
27156     81 7/subop/compare *(ebp+0xc) 0/imm32
27157     0f 84/jump-if-= $emit-subx-disp32:end/disp32
27158     # var v/eax: (addr stmt-var)
27159     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
27160     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27161     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27162     (write-buffered *(ebp+8) Space)
27163     (write-buffered *(ebp+8) %eax)
27164     # hack: if instruction operation starts with "break", emit ":break"
27165     # var name/ecx: (addr array byte) = lookup(stmt->operation)
27166     8b/-> *(ebp+0x10) 0/r32/eax
27167     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27168     89/<- %ecx 0/r32/eax
27169     {
27170       (string-starts-with? %ecx "break")  # => eax
27171       3d/compare-eax-and 0/imm32/false
27172       74/jump-if-= break/disp8
27173       (write-buffered *(ebp+8) ":break")
27174     }
27175     # hack: if instruction operation starts with "loop", emit ":loop"
27176     {
27177       (string-starts-with? %ecx "loop")  # => eax
27178       3d/compare-eax-and 0/imm32/false
27179       74/jump-if-= break/disp8
27180       (write-buffered *(ebp+8) ":loop")
27181     }
27182     (write-buffered *(ebp+8) "/disp32")
27183 $emit-subx-disp32:end:
27184     # . restore registers
27185     59/pop-to-ecx
27186     58/pop-to-eax
27187     # . epilogue
27188     89/<- %esp 5/r32/ebp
27189     5d/pop-to-ebp
27190     c3/return
27191 
27192 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
27193     # . prologue
27194     55/push-ebp
27195     89/<- %ebp 4/r32/esp
27196     # . save registers
27197     50/push-eax
27198     51/push-ecx
27199     #
27200     (emit-indent *(ebp+8) *Curr-block-depth)
27201     (write-buffered *(ebp+8) "(")
27202     # ecx = stmt
27203     8b/-> *(ebp+0xc) 1/r32/ecx
27204     # - emit function name
27205     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27206     (write-buffered *(ebp+8) %eax)
27207     # - emit arguments
27208     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
27209     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27210     {
27211       # if (curr == null) break
27212       3d/compare-eax-and 0/imm32
27213       74/jump-if-= break/disp8
27214       #
27215       (emit-subx-call-operand *(ebp+8) %eax)
27216       # curr = lookup(curr->next)
27217       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27218       eb/jump loop/disp8
27219     }
27220     #
27221     (write-buffered *(ebp+8) ")\n")
27222 $emit-call:end:
27223     # . restore registers
27224     59/pop-to-ecx
27225     58/pop-to-eax
27226     # . epilogue
27227     89/<- %esp 5/r32/ebp
27228     5d/pop-to-ebp
27229     c3/return
27230 
27231 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
27232     # shares code with emit-subx-var-as-rm32
27233     # . prologue
27234     55/push-ebp
27235     89/<- %ebp 4/r32/esp
27236     # . save registers
27237     50/push-eax
27238     51/push-ecx
27239     56/push-esi
27240     # ecx = s
27241     8b/-> *(ebp+0xc) 1/r32/ecx
27242     # var operand/esi: (addr var) = lookup(s->value)
27243     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
27244     89/<- %esi 0/r32/eax
27245     # if (operand->register && !s->is-deref?) emit "%__"
27246     {
27247 $emit-subx-call-operand:check-for-register-direct:
27248       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
27249       74/jump-if-= break/disp8
27250       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27251       75/jump-if-!= break/disp8
27252 $emit-subx-call-operand:register-direct:
27253       (write-buffered *(ebp+8) " %")
27254       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
27255       (write-buffered *(ebp+8) %eax)
27256       e9/jump $emit-subx-call-operand:end/disp32
27257     }
27258     # else if (operand->register && s->is-deref?) emit "*__"
27259     {
27260 $emit-subx-call-operand:check-for-register-indirect:
27261       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
27262       74/jump-if-= break/disp8
27263       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27264       74/jump-if-= break/disp8
27265 $emit-subx-call-operand:register-indirect:
27266       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
27267       e9/jump $emit-subx-call-operand:end/disp32
27268     }
27269     # else if (operand->stack-offset) emit "*(ebp+__)"
27270     {
27271       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
27272       74/jump-if-= break/disp8
27273 $emit-subx-call-operand:stack:
27274       (emit-subx-call-operand-stack *(ebp+8) %esi)
27275       e9/jump $emit-subx-call-operand:end/disp32
27276     }
27277     # else if (operand->type == literal) emit "__"
27278     {
27279       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
27280       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-left
27281       75/jump-if-!= break/disp8
27282 $emit-subx-call-operand:literal:
27283       (write-buffered *(ebp+8) Space)
27284       (lookup *esi *(esi+4))  # Var-name Var-name => eax
27285       (write-buffered *(ebp+8) %eax)
27286     }
27287 $emit-subx-call-operand:end:
27288     # . restore registers
27289     5e/pop-to-esi
27290     59/pop-to-ecx
27291     58/pop-to-eax
27292     # . epilogue
27293     89/<- %esp 5/r32/ebp
27294     5d/pop-to-ebp
27295     c3/return
27296 
27297 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
27298     # . prologue
27299     55/push-ebp
27300     89/<- %ebp 4/r32/esp
27301     # . save registers
27302     50/push-eax
27303     51/push-ecx
27304     56/push-esi
27305     # esi = v
27306     8b/-> *(ebp+0xc) 6/r32/esi
27307     # var size/ecx: int = size-of-deref(v)
27308     (size-of-deref %esi)  # => eax
27309     89/<- %ecx 0/r32/eax
27310     # var reg-name/esi: (addr array byte) = lookup(v->register)
27311     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
27312     89/<- %esi 0/r32/eax
27313     # TODO: assert size is a multiple of 4
27314     # var i/eax: int = 0
27315     b8/copy-to-eax 0/imm32
27316     {
27317 $emit-subx-call-operand-register-indirect:loop:
27318       # if (i >= size) break
27319       39/compare %eax 1/r32/ecx
27320       7d/jump-if->= break/disp8
27321       # emit " *(" v->register "+" i ")"
27322       (write-buffered *(ebp+8) " *(")
27323       (write-buffered *(ebp+8) %esi)
27324       (write-buffered *(ebp+8) "+")
27325       (write-int32-hex-buffered *(ebp+8) %eax)
27326       (write-buffered *(ebp+8) ")")
27327       # i += 4
27328       05/add-to-eax 4/imm32
27329       #
27330       eb/jump loop/disp8
27331     }
27332 $emit-subx-call-operand-register-indirect:end:
27333     # . restore registers
27334     5e/pop-to-esi
27335     59/pop-to-ecx
27336     58/pop-to-eax
27337     # . epilogue
27338     89/<- %esp 5/r32/ebp
27339     5d/pop-to-ebp
27340     c3/return
27341 
27342 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
27343     # . prologue
27344     55/push-ebp
27345     89/<- %ebp 4/r32/esp
27346     # . save registers
27347     50/push-eax
27348     51/push-ecx
27349     56/push-esi
27350     # esi = v
27351     8b/-> *(ebp+0xc) 6/r32/esi
27352     # var curr/ecx: int = v->offset
27353     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
27354     # var max/eax: int = v->offset + size-of(v)
27355     (size-of %esi)  # => eax
27356     # TODO: assert size is a multiple of 4
27357     01/add-to %eax 1/r32/ecx
27358     {
27359 $emit-subx-call-operand-stack:loop:
27360       # if (curr >= max) break
27361       39/compare %ecx 0/r32/eax
27362       7d/jump-if->= break/disp8
27363       # emit " *(ebp+" curr ")"
27364       (write-buffered *(ebp+8) " *(ebp+")
27365       (write-int32-hex-buffered *(ebp+8) %ecx)
27366       (write-buffered *(ebp+8) ")")
27367       # i += 4
27368       81 0/subop/add %ecx 4/imm32
27369       #
27370       eb/jump loop/disp8
27371     }
27372 $emit-subx-call-operand-stack:end:
27373     # . restore registers
27374     5e/pop-to-esi
27375     59/pop-to-ecx
27376     58/pop-to-eax
27377     # . epilogue
27378     89/<- %esp 5/r32/ebp
27379     5d/pop-to-ebp
27380     c3/return
27381 
27382 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
27383     # . prologue
27384     55/push-ebp
27385     89/<- %ebp 4/r32/esp
27386     # . save registers
27387     50/push-eax
27388     51/push-ecx
27389     56/push-esi
27390     # ecx = s
27391     8b/-> *(ebp+0xc) 1/r32/ecx
27392     # var operand/esi: (addr var) = lookup(s->value)
27393     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
27394     89/<- %esi 0/r32/eax
27395     # if (operand->register && s->is-deref?) emit "*__"
27396     {
27397 $emit-subx-var-as-rm32:check-for-register-indirect:
27398       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
27399       74/jump-if-= break/disp8
27400       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27401       74/jump-if-= break/disp8
27402 $emit-subx-var-as-rm32:register-indirect:
27403       (write-buffered *(ebp+8) " *")
27404       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
27405       (write-buffered *(ebp+8) %eax)
27406       e9/jump $emit-subx-var-as-rm32:end/disp32
27407     }
27408     # if (operand->register && !s->is-deref?) emit "%__"
27409     {
27410 $emit-subx-var-as-rm32:check-for-register-direct:
27411       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
27412       74/jump-if-= break/disp8
27413       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27414       75/jump-if-!= break/disp8
27415 $emit-subx-var-as-rm32:register-direct:
27416       (write-buffered *(ebp+8) " %")
27417       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
27418       (write-buffered *(ebp+8) %eax)
27419       e9/jump $emit-subx-var-as-rm32:end/disp32
27420     }
27421     # else if (operand->stack-offset) emit "*(ebp+__)"
27422     {
27423       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
27424       74/jump-if-= break/disp8
27425 $emit-subx-var-as-rm32:stack:
27426       (write-buffered *(ebp+8) Space)
27427       (write-buffered *(ebp+8) "*(ebp+")
27428       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
27429       (write-buffered *(ebp+8) ")")
27430     }
27431 $emit-subx-var-as-rm32:end:
27432     # . restore registers
27433     5e/pop-to-esi
27434     59/pop-to-ecx
27435     58/pop-to-eax
27436     # . epilogue
27437     89/<- %esp 5/r32/ebp
27438     5d/pop-to-ebp
27439     c3/return
27440 
27441 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
27442     # . prologue
27443     55/push-ebp
27444     89/<- %ebp 4/r32/esp
27445     # . save registers
27446     51/push-ecx
27447     # var curr/ecx: (addr primitive) = primitives
27448     8b/-> *(ebp+8) 1/r32/ecx
27449     {
27450 $find-matching-primitive:loop:
27451       # if (curr == null) break
27452       81 7/subop/compare %ecx 0/imm32
27453       74/jump-if-= break/disp8
27454       # if match(curr, stmt) return curr
27455       {
27456         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
27457         3d/compare-eax-and 0/imm32/false
27458         74/jump-if-= break/disp8
27459         89/<- %eax 1/r32/ecx
27460         eb/jump $find-matching-primitive:end/disp8
27461       }
27462 $find-matching-primitive:next-primitive:
27463       # curr = curr->next
27464       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
27465       89/<- %ecx 0/r32/eax
27466       #
27467       e9/jump loop/disp32
27468     }
27469     # return null
27470     b8/copy-to-eax 0/imm32
27471 $find-matching-primitive:end:
27472     # . restore registers
27473     59/pop-to-ecx
27474     # . epilogue
27475     89/<- %esp 5/r32/ebp
27476     5d/pop-to-ebp
27477     c3/return
27478 
27479 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
27480     # A mu stmt matches a primitive if the name matches, all the inout vars
27481     # match, and all the output vars match.
27482     # Vars match if types match and registers match.
27483     # In addition, a stmt output matches a primitive's output if types match
27484     # and the primitive has a wildcard register.
27485     # . prologue
27486     55/push-ebp
27487     89/<- %ebp 4/r32/esp
27488     # . save registers
27489     51/push-ecx
27490     52/push-edx
27491     53/push-ebx
27492     56/push-esi
27493     57/push-edi
27494     # ecx = stmt
27495     8b/-> *(ebp+8) 1/r32/ecx
27496     # edx = primitive
27497     8b/-> *(ebp+0xc) 2/r32/edx
27498     {
27499 $mu-stmt-matches-primitive?:check-name:
27500       # if (primitive->name != stmt->operation) return false
27501       # . var esi: (addr array byte) = lookup(stmt->operation)
27502       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27503       89/<- %esi 0/r32/eax
27504       # . var edi: (addr array byte) = lookup(primitive->name)
27505       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
27506 #?       (write-buffered Stderr %eax)
27507 #?       (write-buffered Stderr Newline)
27508 #?       (flush Stderr)
27509       89/<- %edi 0/r32/eax
27510       (string-equal? %esi %edi)  # => eax
27511       3d/compare-eax-and 0/imm32/false
27512       75/jump-if-!= break/disp8
27513       b8/copy-to-eax 0/imm32
27514       e9/jump $mu-stmt-matches-primitive?:end/disp32
27515     }
27516     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
27517     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27518     89/<- %esi 0/r32/eax
27519     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
27520     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
27521     89/<- %edi 0/r32/eax
27522     {
27523 $mu-stmt-matches-primitive?:inouts-loop:
27524       # if (curr == 0 && curr2 == 0) move on to check outputs
27525       {
27526 $mu-stmt-matches-primitive?:check-both-inouts-null:
27527         81 7/subop/compare %esi 0/imm32
27528         75/jump-if-!= break/disp8
27529 $mu-stmt-matches-primitive?:stmt-inout-null:
27530         81 7/subop/compare %edi 0/imm32
27531         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
27532 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
27533         # return false
27534         b8/copy-to-eax 0/imm32/false
27535         e9/jump $mu-stmt-matches-primitive?:end/disp32
27536       }
27537       # if (curr2 == 0) return false
27538       {
27539 $mu-stmt-matches-primitive?:check-prim-inout-null:
27540         81 7/subop/compare %edi 0/imm32
27541         75/jump-if-!= break/disp8
27542 $mu-stmt-matches-primitive?:prim-inout-null:
27543         b8/copy-to-eax 0/imm32/false
27544         e9/jump $mu-stmt-matches-primitive?:end/disp32
27545       }
27546       # if (curr != curr2) return false
27547       {
27548 $mu-stmt-matches-primitive?:check-inouts-match:
27549         (lookup *edi *(edi+4))  # List-value List-value => eax
27550         (operand-matches-primitive? %esi %eax)  # => eax
27551         3d/compare-eax-and 0/imm32/false
27552         75/jump-if-!= break/disp8
27553 $mu-stmt-matches-primitive?:inouts-match:
27554         b8/copy-to-eax 0/imm32/false
27555         e9/jump $mu-stmt-matches-primitive?:end/disp32
27556       }
27557 $mu-stmt-matches-primitive?:next-inout:
27558       # curr = lookup(curr->next)
27559       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27560       89/<- %esi 0/r32/eax
27561       # curr2 = lookup(curr2->next)
27562       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27563       89/<- %edi 0/r32/eax
27564       #
27565       e9/jump loop/disp32
27566     }
27567 $mu-stmt-matches-primitive?:check-outputs:
27568     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
27569     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27570     89/<- %esi 0/r32/eax
27571     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
27572     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
27573     89/<- %edi 0/r32/eax
27574     {
27575 $mu-stmt-matches-primitive?:outputs-loop:
27576       # if (curr == 0) return (curr2 == 0)
27577       {
27578 $mu-stmt-matches-primitive?:check-both-outputs-null:
27579         81 7/subop/compare %esi 0/imm32
27580         75/jump-if-!= break/disp8
27581         {
27582 $mu-stmt-matches-primitive?:stmt-output-null:
27583           81 7/subop/compare %edi 0/imm32
27584           75/jump-if-!= break/disp8
27585 $mu-stmt-matches-primitive?:both-outputs-null:
27586           # return true
27587           b8/copy-to-eax 1/imm32
27588           e9/jump $mu-stmt-matches-primitive?:end/disp32
27589         }
27590 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
27591         # return false
27592         b8/copy-to-eax 0/imm32
27593         e9/jump $mu-stmt-matches-primitive?:end/disp32
27594       }
27595       # if (curr2 == 0) return false
27596       {
27597 $mu-stmt-matches-primitive?:check-prim-output-null:
27598         81 7/subop/compare %edi 0/imm32
27599         75/jump-if-!= break/disp8
27600 $mu-stmt-matches-primitive?:prim-output-is-null:
27601         b8/copy-to-eax 0/imm32
27602         e9/jump $mu-stmt-matches-primitive?:end/disp32
27603       }
27604       # if (curr != curr2) return false
27605       {
27606 $mu-stmt-matches-primitive?:check-outputs-match:
27607         (lookup *edi *(edi+4))  # List-value List-value => eax
27608         (operand-matches-primitive? %esi %eax)  # => eax
27609         3d/compare-eax-and 0/imm32/false
27610         75/jump-if-!= break/disp8
27611 $mu-stmt-matches-primitive?:outputs-match:
27612         b8/copy-to-eax 0/imm32
27613         e9/jump $mu-stmt-matches-primitive?:end/disp32
27614       }
27615 $mu-stmt-matches-primitive?:next-output:
27616       # curr = lookup(curr->next)
27617       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27618       89/<- %esi 0/r32/eax
27619       # curr2 = lookup(curr2->next)
27620       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27621       89/<- %edi 0/r32/eax
27622       #
27623       e9/jump loop/disp32
27624     }
27625 $mu-stmt-matches-primitive?:return-true:
27626     b8/copy-to-eax 1/imm32
27627 $mu-stmt-matches-primitive?:end:
27628     # . restore registers
27629     5f/pop-to-edi
27630     5e/pop-to-esi
27631     5b/pop-to-ebx
27632     5a/pop-to-edx
27633     59/pop-to-ecx
27634     # . epilogue
27635     89/<- %esp 5/r32/ebp
27636     5d/pop-to-ebp
27637     c3/return
27638 
27639 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
27640     # . prologue
27641     55/push-ebp
27642     89/<- %ebp 4/r32/esp
27643     # . save registers
27644     51/push-ecx
27645     52/push-edx
27646     53/push-ebx
27647     56/push-esi
27648     57/push-edi
27649     # ecx = s
27650     8b/-> *(ebp+8) 1/r32/ecx
27651     # var var/esi: (addr var) = lookup(s->value)
27652     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
27653     89/<- %esi 0/r32/eax
27654     # edi = prim-var
27655     8b/-> *(ebp+0xc) 7/r32/edi
27656 $operand-matches-primitive?:check-type:
27657     # if !category-match?(var->type, prim-var->type) return false
27658     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
27659     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
27660     89/<- %ebx 0/r32/eax
27661     # . if s is deref, vtype = vtype->right
27662     {
27663       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27664       74/jump-if-= break/disp8
27665 $operand-matches-primitive?:is-deref:
27666       # . var t/eax: (addr type)
27667       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
27668       # . if !t->is-atom? t = t->left
27669       81 7/subop/compare *eax 0/imm32/false
27670       {
27671         75/jump-if-!= break/disp8
27672         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27673       }
27674       # .
27675       89/<- %ebx 0/r32/eax
27676     }
27677     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
27678     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
27679     (subx-type-category-match? %ebx %eax)  # => eax
27680     3d/compare-eax-and 0/imm32/false
27681     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
27682     {
27683 $operand-matches-primitive?:check-register:
27684       # if prim-var is in memory and var is in register but dereference, match
27685       {
27686         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
27687         0f 85/jump-if-!= break/disp32
27688         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
27689         74/jump-if-= break/disp8
27690         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27691         74/jump-if-= break/disp8
27692 $operand-matches-primitive?:var-deref-match:
27693         e9/jump $operand-matches-primitive?:return-true/disp32
27694       }
27695       # if prim-var is in register and var is in register but dereference, no match
27696       {
27697         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
27698         0f 84/jump-if-= break/disp32
27699         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
27700         0f 84/jump-if-= break/disp32
27701         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
27702         74/jump-if-= break/disp8
27703 $operand-matches-primitive?:var-deref-no-match:
27704         e9/jump $operand-matches-primitive?:return-false/disp32
27705       }
27706       # return false if var->register doesn't match prim-var->register
27707       {
27708         # if register addresses are equal, it's a match
27709         # var vreg/ebx: (addr array byte) = lookup(var->register)
27710         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
27711         89/<- %ebx 0/r32/eax
27712         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
27713         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
27714         89/<- %ecx 0/r32/eax
27715         # if (vreg == preg) break
27716         39/compare %ecx 3/r32/ebx
27717         74/jump-if-= break/disp8
27718 $operand-matches-primitive?:var-register-no-match:
27719         # if either address is 0, return false
27720         81 7/subop/compare %ebx 0/imm32
27721         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
27722         81 7/subop/compare %ecx 0/imm32
27723         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
27724         # if prim-var->register is wildcard, it's a match
27725         (string-equal? %ecx "*")  # Any-register => eax
27726         3d/compare-eax-and 0/imm32/false
27727         75/jump-if-!= break/disp8
27728 $operand-matches-primitive?:wildcard-no-match:
27729         # if string contents aren't equal, return false
27730         (string-equal? %ecx %ebx)  # => eax
27731         3d/compare-eax-and 0/imm32/false
27732         74/jump-if-= $operand-matches-primitive?:return-false/disp8
27733       }
27734     }
27735 $operand-matches-primitive?:return-true:
27736     b8/copy-to-eax 1/imm32/true
27737     eb/jump $operand-matches-primitive?:end/disp8
27738 $operand-matches-primitive?:return-false:
27739     b8/copy-to-eax 0/imm32/false
27740 $operand-matches-primitive?:end:
27741     # . restore registers
27742     5f/pop-to-edi
27743     5e/pop-to-esi
27744     5b/pop-to-ebx
27745     5a/pop-to-edx
27746     59/pop-to-ecx
27747     # . epilogue
27748     89/<- %esp 5/r32/ebp
27749     5d/pop-to-ebp
27750     c3/return
27751 
27752 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
27753     # . prologue
27754     55/push-ebp
27755     89/<- %ebp 4/r32/esp
27756     # . save registers
27757     51/push-ecx
27758     # var curr/ecx: (handle function) = functions
27759     8b/-> *(ebp+8) 1/r32/ecx
27760     {
27761       # if (curr == null) break
27762       81 7/subop/compare %ecx 0/imm32
27763       74/jump-if-= break/disp8
27764 #?       (write-buffered Stderr "iter\n")
27765 #?       (flush Stderr)
27766       # if match(stmt, curr) return curr
27767       {
27768         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
27769         3d/compare-eax-and 0/imm32/false
27770         74/jump-if-= break/disp8
27771         89/<- %eax 1/r32/ecx
27772         eb/jump $find-matching-function:end/disp8
27773       }
27774       # curr = curr->next
27775       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
27776       89/<- %ecx 0/r32/eax
27777       #
27778       eb/jump loop/disp8
27779     }
27780     # return null
27781     b8/copy-to-eax 0/imm32
27782 $find-matching-function:end:
27783     # . restore registers
27784     59/pop-to-ecx
27785     # . epilogue
27786     89/<- %esp 5/r32/ebp
27787     5d/pop-to-ebp
27788     c3/return
27789 
27790 # Just compare names; user-defined functions don't support overloading yet.
27791 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
27792     # . prologue
27793     55/push-ebp
27794     89/<- %ebp 4/r32/esp
27795     # . save registers
27796     51/push-ecx
27797     # return function->name == stmt->operation
27798     # ecx = lookup(stmt->operation)
27799     8b/-> *(ebp+8) 0/r32/eax
27800     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27801     89/<- %ecx 0/r32/eax
27802     # eax = lookup(function->name)
27803     8b/-> *(ebp+0xc) 0/r32/eax
27804     (lookup *eax *(eax+4))  # Function-name Function-name => eax
27805     (string-equal? %eax %ecx)  # => eax
27806 $mu-stmt-matches-function?:end:
27807     # . restore registers
27808     59/pop-to-ecx
27809     # . epilogue
27810     89/<- %esp 5/r32/ebp
27811     5d/pop-to-ebp
27812     c3/return
27813 
27814 # Type-checking happens elsewhere. This method is for selecting between
27815 # primitives.
27816 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
27817     # . prologue
27818     55/push-ebp
27819     89/<- %ebp 4/r32/esp
27820     # . save registers
27821     51/push-ecx
27822     # var cata/ecx: int = type-category(a)
27823     (type-category *(ebp+8))  # => eax
27824     89/<- %ecx 0/r32/eax
27825     # var catb/eax: int = type-category(b)
27826     (type-category *(ebp+0xc))  # => eax
27827     # return cata == catb
27828     39/compare %eax 1/r32/ecx
27829     0f 94/set-byte-if-= %al
27830     81 4/subop/and %eax 0xff/imm32
27831 $subx-type-category-match?:end:
27832     # . restore registers
27833     59/pop-to-ecx
27834     # . epilogue
27835     89/<- %esp 5/r32/ebp
27836     5d/pop-to-ebp
27837     c3/return
27838 
27839 type-category:  # a: (addr type-tree) -> result/eax: int
27840     # . prologue
27841     55/push-ebp
27842     89/<- %ebp 4/r32/esp
27843     # . save registers
27844     51/push-ecx
27845     # var lit?/ecx: boolean = is-literal-type?(a)
27846     (is-simple-mu-type? *(ebp+8) 0)  # => eax
27847     89/<- %ecx 0/r32/eax
27848     # var float?/eax: int = is-float?(a)
27849     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
27850     # set bits for lit? and float?
27851     c1/shift 4/subop/left %ecx 1/imm8
27852     09/or %eax 1/r32/ecx
27853 $type-category:end:
27854     # . restore registers
27855     59/pop-to-ecx
27856     # . epilogue
27857     89/<- %esp 5/r32/ebp
27858     5d/pop-to-ebp
27859     c3/return
27860 
27861 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
27862     # . prologue
27863     55/push-ebp
27864     89/<- %ebp 4/r32/esp
27865     # . save registers
27866     51/push-ecx
27867     # ecx = n
27868     8b/-> *(ebp+0xc) 1/r32/ecx
27869     # return (a->value == n)
27870     8b/-> *(ebp+8) 0/r32/eax
27871     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
27872     0f 94/set-byte-if-= %al
27873     81 4/subop/and %eax 0xff/imm32
27874 $is-simple-mu-type?:end:
27875     # . restore registers
27876     59/pop-to-ecx
27877     # . epilogue
27878     89/<- %esp 5/r32/ebp
27879     5d/pop-to-ebp
27880     c3/return
27881 
27882 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
27883     # . prologue
27884     55/push-ebp
27885     89/<- %ebp 4/r32/esp
27886     # eax = a
27887     8b/-> *(ebp+8) 0/r32/eax
27888     # if (!a->is-atom?) a = a->left
27889     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27890     {
27891       75/jump-if-!= break/disp8
27892       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27893     }
27894     # return (a->value == addr)
27895     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
27896     0f 94/set-byte-if-= %al
27897     81 4/subop/and %eax 0xff/imm32
27898 $is-mu-addr-type?:end:
27899     # . epilogue
27900     89/<- %esp 5/r32/ebp
27901     5d/pop-to-ebp
27902     c3/return
27903 
27904 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
27905     # . prologue
27906     55/push-ebp
27907     89/<- %ebp 4/r32/esp
27908     # eax = a
27909     8b/-> *(ebp+8) 0/r32/eax
27910     # if (!a->is-atom?) a = a->left
27911     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27912     {
27913       75/jump-if-!= break/disp8
27914       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27915     }
27916     # return (a->value == array)
27917     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
27918     0f 94/set-byte-if-= %al
27919     81 4/subop/and %eax 0xff/imm32
27920 $is-mu-array-type?:end:
27921     # . epilogue
27922     89/<- %esp 5/r32/ebp
27923     5d/pop-to-ebp
27924     c3/return
27925 
27926 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
27927     # . prologue
27928     55/push-ebp
27929     89/<- %ebp 4/r32/esp
27930     # eax = a
27931     8b/-> *(ebp+8) 0/r32/eax
27932     # if (!a->is-atom?) a = a->left
27933     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27934     {
27935       75/jump-if-!= break/disp8
27936       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27937     }
27938     # return (a->value == stream)
27939     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
27940     0f 94/set-byte-if-= %al
27941     81 4/subop/and %eax 0xff/imm32
27942 $is-mu-stream-type?:end:
27943     # . epilogue
27944     89/<- %esp 5/r32/ebp
27945     5d/pop-to-ebp
27946     c3/return
27947 
27948 test-emit-subx-stmt-primitive:
27949     # Primitive operation on a variable on the stack.
27950     #   increment foo
27951     # =>
27952     #   ff 0/subop/increment *(ebp-8)
27953     #
27954     # There's a variable on the var stack as follows:
27955     #   name: 'foo'
27956     #   type: int
27957     #   stack-offset: -8
27958     #
27959     # There's a primitive with this info:
27960     #   name: 'increment'
27961     #   inouts: int/mem
27962     #   value: 'ff 0/subop/increment'
27963     #
27964     # . prologue
27965     55/push-ebp
27966     89/<- %ebp 4/r32/esp
27967     # setup
27968     (clear-stream _test-output-stream)
27969     (clear-stream $_test-output-buffered-file->buffer)
27970     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
27971 $test-emit-subx-stmt-primitive:initialize-type:
27972     # var type/ecx: (payload type-tree) = int
27973     68/push 0/imm32/right:null
27974     68/push 0/imm32/right:null
27975     68/push 0/imm32/left:unused
27976     68/push 1/imm32/value:int
27977     68/push 1/imm32/is-atom?:true
27978     68/push 0x11/imm32/alloc-id:fake:payload
27979     89/<- %ecx 4/r32/esp
27980 $test-emit-subx-stmt-primitive:initialize-var:
27981     # var var-foo/ecx: (payload var) = var(type)
27982     68/push 0/imm32/no-register
27983     68/push 0/imm32/no-register
27984     68/push -8/imm32/stack-offset
27985     68/push 1/imm32/block-depth
27986     51/push-ecx/type
27987     68/push 0x11/imm32/alloc-id:fake
27988     68/push 0/imm32/name
27989     68/push 0/imm32/name
27990     68/push 0x11/imm32/alloc-id:fake:payload
27991     89/<- %ecx 4/r32/esp
27992 $test-emit-subx-stmt-primitive:initialize-var-name:
27993     # var-foo->name = "foo"
27994     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27995     (copy-array Heap "foo" %eax)
27996 $test-emit-subx-stmt-primitive:initialize-stmt-var:
27997     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
27998     68/push 0/imm32/is-deref:false
27999     68/push 0/imm32/next
28000     68/push 0/imm32/next
28001     51/push-ecx/var-foo
28002     68/push 0x11/imm32/alloc-id:fake
28003     68/push 0x11/imm32/alloc-id:fake:payload
28004     89/<- %ebx 4/r32/esp
28005 $test-emit-subx-stmt-primitive:initialize-stmt:
28006     # var stmt/esi: (addr statement)
28007     68/push 0/imm32/no-outputs
28008     68/push 0/imm32/no-outputs
28009     53/push-ebx/inouts
28010     68/push 0x11/imm32/alloc-id:fake
28011     68/push 0/imm32/operation
28012     68/push 0/imm32/operation
28013     68/push 1/imm32/tag
28014     89/<- %esi 4/r32/esp
28015 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
28016     # stmt->operation = "increment"
28017     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28018     (copy-array Heap "increment" %eax)
28019 $test-emit-subx-stmt-primitive:initialize-primitive:
28020     # var primitives/ebx: (addr primitive)
28021     68/push 0/imm32/next
28022     68/push 0/imm32/next
28023     68/push 0/imm32/no-x32
28024     68/push 0/imm32/no-xm32
28025     68/push 0/imm32/no-disp32
28026     68/push 0/imm32/no-imm8
28027     68/push 0/imm32/no-imm32
28028     68/push 0/imm32/no-r32
28029     68/push 1/imm32/rm32-is-first-inout
28030     68/push 0/imm32/subx-name
28031     68/push 0/imm32/subx-name
28032     68/push 0/imm32/no-outputs
28033     68/push 0/imm32/no-outputs
28034     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
28035     68/push 0x11/imm32/alloc-id:fake
28036     68/push 0/imm32/name
28037     68/push 0/imm32/name
28038     89/<- %ebx 4/r32/esp
28039 $test-emit-subx-stmt-primitive:initialize-primitive-name:
28040     # primitives->name = "increment"
28041     (copy-array Heap "increment" %ebx)  # Primitive-name
28042 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
28043     # primitives->subx-name = "ff 0/subop/increment"
28044     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
28045     (copy-array Heap "ff 0/subop/increment" %eax)
28046     # convert
28047     c7 0/subop/copy *Curr-block-depth 0/imm32
28048     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
28049     (flush _test-output-buffered-file)
28050 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28056     # check output
28057     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
28058     # . epilogue
28059     89/<- %esp 5/r32/ebp
28060     5d/pop-to-ebp
28061     c3/return
28062 
28063 test-emit-subx-stmt-primitive-register:
28064     # Primitive operation on a variable in a register.
28065     #   foo <- increment
28066     # =>
28067     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
28068     #
28069     # There's a variable on the var stack as follows:
28070     #   name: 'foo'
28071     #   type: int
28072     #   register: 'eax'
28073     #
28074     # There's a primitive with this info:
28075     #   name: 'increment'
28076     #   out: int/reg
28077     #   value: 'ff 0/subop/increment'
28078     #
28079     # . prologue
28080     55/push-ebp
28081     89/<- %ebp 4/r32/esp
28082     # setup
28083     (clear-stream _test-output-stream)
28084     (clear-stream $_test-output-buffered-file->buffer)
28085 $test-emit-subx-stmt-primitive-register:initialize-type:
28086     # var type/ecx: (payload type-tree) = int
28087     68/push 0/imm32/right:null
28088     68/push 0/imm32/right:null
28089     68/push 0/imm32/left:unused
28090     68/push 1/imm32/value:int
28091     68/push 1/imm32/is-atom?:true
28092     68/push 0x11/imm32/alloc-id:fake:payload
28093     89/<- %ecx 4/r32/esp
28094 $test-emit-subx-stmt-primitive-register:initialize-var:
28095     # var var-foo/ecx: (payload var)
28096     68/push 0/imm32/register
28097     68/push 0/imm32/register
28098     68/push 0/imm32/no-stack-offset
28099     68/push 1/imm32/block-depth
28100     51/push-ecx
28101     68/push 0x11/imm32/alloc-id:fake
28102     68/push 0/imm32/name
28103     68/push 0/imm32/name
28104     68/push 0x11/imm32/alloc-id:fake:payload
28105     89/<- %ecx 4/r32/esp
28106 $test-emit-subx-stmt-primitive-register:initialize-var-name:
28107     # var-foo->name = "foo"
28108     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28109     (copy-array Heap "foo" %eax)
28110 $test-emit-subx-stmt-primitive-register:initialize-var-register:
28111     # var-foo->register = "eax"
28112     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28113     (copy-array Heap "eax" %eax)
28114 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
28115     # var operand/ebx: (payload stmt-var)
28116     68/push 0/imm32/is-deref:false
28117     68/push 0/imm32/next
28118     68/push 0/imm32/next
28119     51/push-ecx/var-foo
28120     68/push 0x11/imm32/alloc-id:fake
28121     68/push 0x11/imm32/alloc-id:fake:payload
28122     89/<- %ebx 4/r32/esp
28123 $test-emit-subx-stmt-primitive-register:initialize-stmt:
28124     # var stmt/esi: (addr statement)
28125     53/push-ebx/outputs
28126     68/push 0x11/imm32/alloc-id:fake
28127     68/push 0/imm32/no-inouts
28128     68/push 0/imm32/no-inouts
28129     68/push 0/imm32/operation
28130     68/push 0/imm32/operation
28131     68/push 1/imm32
28132     89/<- %esi 4/r32/esp
28133 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
28134     # stmt->operation = "increment"
28135     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28136     (copy-array Heap "increment" %eax)
28137 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
28138     # var formal-var/ebx: (payload var)
28139     68/push 0/imm32/register
28140     68/push 0/imm32/register
28141     68/push 0/imm32/no-stack-offset
28142     68/push 1/imm32/block-depth
28143     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
28144     68/push 0x11/imm32/alloc-id:fake
28145     68/push 0/imm32/name
28146     68/push 0/imm32/name
28147     68/push 0x11/imm32/alloc-id:fake:payload
28148     89/<- %ebx 4/r32/esp
28149 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
28150     # formal-var->name = "dummy"
28151     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
28152     (copy-array Heap "dummy" %eax)
28153 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
28154     # formal-var->register = "*"
28155     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
28156     (copy-array Heap "*" %eax)  # Any-register
28157 $test-emit-subx-stmt-primitive-register:initialize-var-list:
28158     # var formal-outputs/ebx: (payload list var)
28159     68/push 0/imm32/next
28160     68/push 0/imm32/next
28161     53/push-ebx/formal-var
28162     68/push 0x11/imm32/alloc-id:fake
28163     68/push 0x11/imm32/alloc-id:fake:payload
28164     89/<- %ebx 4/r32/esp
28165 $test-emit-subx-stmt-primitive-register:initialize-primitive:
28166     # var primitives/ebx: (addr primitive)
28167     68/push 0/imm32/next
28168     68/push 0/imm32/next
28169     68/push 0/imm32/no-x32
28170     68/push 0/imm32/no-xm32
28171     68/push 0/imm32/no-disp32
28172     68/push 0/imm32/no-imm8
28173     68/push 0/imm32/no-imm32
28174     68/push 0/imm32/no-r32
28175     68/push 3/imm32/rm32-is-first-output
28176     68/push 0/imm32/subx-name
28177     68/push 0/imm32/subx-name
28178     53/push-ebx/outputs
28179     68/push 0x11/imm32/alloc-id:fake
28180     68/push 0/imm32/no-inouts
28181     68/push 0/imm32/no-inouts
28182     68/push 0/imm32/name
28183     68/push 0/imm32/name
28184     89/<- %ebx 4/r32/esp
28185 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
28186     # primitives->name = "increment"
28187     (copy-array Heap "increment" %ebx)  # Primitive-name
28188 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
28189     # primitives->subx-name = "ff 0/subop/increment"
28190     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
28191     (copy-array Heap "ff 0/subop/increment" %eax)
28192     # convert
28193     c7 0/subop/copy *Curr-block-depth 0/imm32
28194     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
28195     (flush _test-output-buffered-file)
28196 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28202     # check output
28203     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
28204     # . epilogue
28205     89/<- %esp 5/r32/ebp
28206     5d/pop-to-ebp
28207     c3/return
28208 
28209 test-emit-subx-stmt-select-primitive:
28210     # Select the right primitive between overloads.
28211     #   foo <- increment
28212     # =>
28213     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
28214     #
28215     # There's a variable on the var stack as follows:
28216     #   name: 'foo'
28217     #   type: int
28218     #   register: 'eax'
28219     #
28220     # There's two primitives, as follows:
28221     #   - name: 'increment'
28222     #     out: int/reg
28223     #     value: 'ff 0/subop/increment'
28224     #   - name: 'increment'
28225     #     inout: int/mem
28226     #     value: 'ff 0/subop/increment'
28227     #
28228     # . prologue
28229     55/push-ebp
28230     89/<- %ebp 4/r32/esp
28231     # setup
28232     (clear-stream _test-output-stream)
28233     (clear-stream $_test-output-buffered-file->buffer)
28234 $test-emit-subx-stmt-select-primitive:initialize-type:
28235     # var type/ecx: (payload type-tree) = int
28236     68/push 0/imm32/right:null
28237     68/push 0/imm32/right:null
28238     68/push 0/imm32/left:unused
28239     68/push 1/imm32/value:int
28240     68/push 1/imm32/is-atom?:true
28241     68/push 0x11/imm32/alloc-id:fake:payload
28242     89/<- %ecx 4/r32/esp
28243 $test-emit-subx-stmt-select-primitive:initialize-var:
28244     # var var-foo/ecx: (payload var)
28245     68/push 0/imm32/register
28246     68/push 0/imm32/register
28247     68/push 0/imm32/no-stack-offset
28248     68/push 1/imm32/block-depth
28249     51/push-ecx
28250     68/push 0x11/imm32/alloc-id:fake
28251     68/push 0/imm32/name
28252     68/push 0/imm32/name
28253     68/push 0x11/imm32/alloc-id:fake:payload
28254     89/<- %ecx 4/r32/esp
28255 $test-emit-subx-stmt-select-primitive:initialize-var-name:
28256     # var-foo->name = "foo"
28257     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28258     (copy-array Heap "foo" %eax)
28259 $test-emit-subx-stmt-select-primitive:initialize-var-register:
28260     # var-foo->register = "eax"
28261     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28262     (copy-array Heap "eax" %eax)
28263 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
28264     # var operand/ebx: (payload stmt-var)
28265     68/push 0/imm32/is-deref:false
28266     68/push 0/imm32/next
28267     68/push 0/imm32/next
28268     51/push-ecx/var-foo
28269     68/push 0x11/imm32/alloc-id:fake
28270     68/push 0x11/imm32/alloc-id:fake:payload
28271     89/<- %ebx 4/r32/esp
28272 $test-emit-subx-stmt-select-primitive:initialize-stmt:
28273     # var stmt/esi: (addr statement)
28274     53/push-ebx/outputs
28275     68/push 0x11/imm32/alloc-id:fake
28276     68/push 0/imm32/no-inouts
28277     68/push 0/imm32/no-inouts
28278     68/push 0/imm32/operation
28279     68/push 0/imm32/operation
28280     68/push 1/imm32
28281     89/<- %esi 4/r32/esp
28282 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
28283     # stmt->operation = "increment"
28284     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28285     (copy-array Heap "increment" %eax)
28286 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
28287     # var formal-var/ebx: (payload var)
28288     68/push 0/imm32/register
28289     68/push 0/imm32/register
28290     68/push 0/imm32/no-stack-offset
28291     68/push 1/imm32/block-depth
28292     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
28293     68/push 0x11/imm32/alloc-id:fake
28294     68/push 0/imm32/name
28295     68/push 0/imm32/name
28296     68/push 0x11/imm32/alloc-id:fake:payload
28297     89/<- %ebx 4/r32/esp
28298 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
28299     # formal-var->name = "dummy"
28300     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
28301     (copy-array Heap "dummy" %eax)
28302 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
28303     # formal-var->register = "*"
28304     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
28305     (copy-array Heap "*" %eax)  # Any-register
28306 $test-emit-subx-stmt-select-primitive:initialize-var-list:
28307     # var formal-outputs/ebx: (payload list var)
28308     68/push 0/imm32/next
28309     68/push 0/imm32/next
28310     53/push-ebx/formal-var
28311     68/push 0x11/imm32/alloc-id:fake
28312     68/push 0x11/imm32/alloc-id:fake:payload
28313     89/<- %ebx 4/r32/esp
28314 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
28315     # var primitive2/edi: (payload primitive)
28316     68/push 0/imm32/next
28317     68/push 0/imm32/next
28318     68/push 0/imm32/no-x32
28319     68/push 0/imm32/no-xm32
28320     68/push 0/imm32/no-disp32
28321     68/push 0/imm32/no-imm8
28322     68/push 0/imm32/no-imm32
28323     68/push 0/imm32/no-r32
28324     68/push 3/imm32/rm32-is-first-output
28325     68/push 0/imm32/subx-name
28326     68/push 0/imm32/subx-name
28327     53/push-ebx/outputs
28328     68/push 0x11/imm32/alloc-id:fake
28329     68/push 0/imm32/no-inouts
28330     68/push 0/imm32/no-inouts
28331     68/push 0/imm32/name
28332     68/push 0/imm32/name
28333     68/push 0x11/imm32/alloc-id:fake:payload
28334     89/<- %edi 4/r32/esp
28335 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
28336     # primitives->name = "increment"
28337     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
28338     (copy-array Heap "increment" %eax)
28339 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
28340     # primitives->subx-name = "ff 0/subop/increment"
28341     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
28342     (copy-array Heap "ff 0/subop/increment" %eax)
28343 $test-emit-subx-stmt-select-primitive:initialize-primitive:
28344     # var primitives/ebx: (addr primitive)
28345     57/push-edi
28346     68/push 0x11/imm32/alloc-id:fake
28347     68/push 0/imm32/no-x32
28348     68/push 0/imm32/no-xm32
28349     68/push 0/imm32/no-disp32
28350     68/push 0/imm32/no-imm8
28351     68/push 0/imm32/no-imm32
28352     68/push 0/imm32/no-r32
28353     68/push 1/imm32/rm32-is-first-inout
28354     68/push 0/imm32/subx-name
28355     68/push 0/imm32/subx-name
28356     68/push 0/imm32/no-outputs
28357     68/push 0/imm32/no-outputs
28358     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
28359     68/push 0x11/imm32/alloc-id:fake
28360     68/push 0/imm32/name
28361     68/push 0/imm32/name
28362     89/<- %ebx 4/r32/esp
28363 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
28364     # primitives->name = "increment"
28365     (copy-array Heap "increment" %ebx)  # Primitive-name
28366 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
28367     # primitives->subx-name = "ff 0/subop/increment"
28368     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
28369     (copy-array Heap "ff 0/subop/increment" %eax)
28370     # convert
28371     c7 0/subop/copy *Curr-block-depth 0/imm32
28372     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
28373     (flush _test-output-buffered-file)
28374 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28380     # check output
28381     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
28382     # . epilogue
28383     89/<- %esp 5/r32/ebp
28384     5d/pop-to-ebp
28385     c3/return
28386 
28387 test-emit-subx-stmt-select-primitive-2:
28388     # Select the right primitive between overloads.
28389     #   increment foo
28390     # =>
28391     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
28392     #
28393     # There's a variable on the var stack as follows:
28394     #   name: 'foo'
28395     #   type: int
28396     #   register: 'eax'
28397     #
28398     # There's two primitives, as follows:
28399     #   - name: 'increment'
28400     #     out: int/reg
28401     #     value: 'ff 0/subop/increment'
28402     #   - name: 'increment'
28403     #     inout: int/mem
28404     #     value: 'ff 0/subop/increment'
28405     #
28406     # . prologue
28407     55/push-ebp
28408     89/<- %ebp 4/r32/esp
28409     # setup
28410     (clear-stream _test-output-stream)
28411     (clear-stream $_test-output-buffered-file->buffer)
28412 $test-emit-subx-stmt-select-primitive-2:initialize-type:
28413     # var type/ecx: (payload type-tree) = int
28414     68/push 0/imm32/right:null
28415     68/push 0/imm32/right:null
28416     68/push 0/imm32/left:unused
28417     68/push 1/imm32/value:int
28418     68/push 1/imm32/is-atom?:true
28419     68/push 0x11/imm32/alloc-id:fake:payload
28420     89/<- %ecx 4/r32/esp
28421 $test-emit-subx-stmt-select-primitive-2:initialize-var:
28422     # var var-foo/ecx: (payload var)
28423     68/push 0/imm32/register
28424     68/push 0/imm32/register
28425     68/push 0/imm32/no-stack-offset
28426     68/push 1/imm32/block-depth
28427     51/push-ecx
28428     68/push 0x11/imm32/alloc-id:fake
28429     68/push 0/imm32/name
28430     68/push 0/imm32/name
28431     68/push 0x11/imm32/alloc-id:fake:payload
28432     89/<- %ecx 4/r32/esp
28433 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
28434     # var-foo->name = "foo"
28435     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28436     (copy-array Heap "foo" %eax)
28437 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
28438     # var-foo->register = "eax"
28439     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28440     (copy-array Heap "eax" %eax)
28441 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
28442     # var operand/ebx: (payload stmt-var)
28443     68/push 0/imm32/is-deref:false
28444     68/push 0/imm32/next
28445     68/push 0/imm32/next
28446     51/push-ecx/var-foo
28447     68/push 0x11/imm32/alloc-id:fake
28448     68/push 0x11/imm32/alloc-id:fake:payload
28449     89/<- %ebx 4/r32/esp
28450 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
28451     # var stmt/esi: (addr statement)
28452     68/push 0/imm32/no-outputs
28453     68/push 0/imm32/no-outputs
28454     53/push-ebx/inouts
28455     68/push 0x11/imm32/alloc-id:fake
28456     68/push 0/imm32/operation
28457     68/push 0/imm32/operation
28458     68/push 1/imm32
28459     89/<- %esi 4/r32/esp
28460 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
28461     # stmt->operation = "increment"
28462     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28463     (copy-array Heap "increment" %eax)
28464 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
28465     # var formal-var/ebx: (payload var)
28466     68/push 0/imm32/register
28467     68/push 0/imm32/register
28468     68/push 0/imm32/no-stack-offset
28469     68/push 1/imm32/block-depth
28470     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
28471     68/push 0x11/imm32/alloc-id:fake
28472     68/push 0/imm32/name
28473     68/push 0/imm32/name
28474     68/push 0x11/imm32/alloc-id:fake:payload
28475     89/<- %ebx 4/r32/esp
28476 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
28477     # formal-var->name = "dummy"
28478     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
28479     (copy-array Heap "dummy" %eax)
28480 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
28481     # formal-var->register = "*"
28482     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
28483     (copy-array Heap "*" %eax)  # Any-register
28484 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
28485     # var formal-outputs/ebx: (payload list stmt-var)
28486     68/push 0/imm32/next
28487     68/push 0/imm32/next
28488     53/push-ebx/formal-var
28489     68/push 0x11/imm32/alloc-id:fake
28490     68/push 0x11/imm32/alloc-id:fake:payload
28491     89/<- %ebx 4/r32/esp
28492 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
28493     # var primitive2/edi: (payload primitive)
28494     68/push 0/imm32/next
28495     68/push 0/imm32/next
28496     68/push 0/imm32/no-x32
28497     68/push 0/imm32/no-xm32
28498     68/push 0/imm32/no-disp32
28499     68/push 0/imm32/no-imm8
28500     68/push 0/imm32/no-imm32
28501     68/push 0/imm32/no-r32
28502     68/push 3/imm32/rm32-is-first-output
28503     68/push 0/imm32/subx-name
28504     68/push 0/imm32/subx-name
28505     53/push-ebx/outputs
28506     68/push 0x11/imm32/alloc-id:fake
28507     68/push 0/imm32/no-inouts
28508     68/push 0/imm32/no-inouts
28509     68/push 0/imm32/name
28510     68/push 0/imm32/name
28511     68/push 0x11/imm32/alloc-id:fake:payload
28512     89/<- %edi 4/r32/esp
28513 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
28514     # primitives->name = "increment"
28515     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
28516     (copy-array Heap "increment" %eax)
28517 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
28518     # primitives->subx-name = "ff 0/subop/increment"
28519     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
28520     (copy-array Heap "ff 0/subop/increment" %eax)
28521 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
28522     # var primitives/ebx: (addr primitive)
28523     57/push-edi
28524     68/push 0x11/imm32/alloc-id:fake
28525     68/push 0/imm32/no-x32
28526     68/push 0/imm32/no-xm32
28527     68/push 0/imm32/no-disp32
28528     68/push 0/imm32/no-imm8
28529     68/push 0/imm32/no-imm32
28530     68/push 0/imm32/no-r32
28531     68/push 1/imm32/rm32-is-first-inout
28532     68/push 0/imm32/subx-name
28533     68/push 0/imm32/subx-name
28534     68/push 0/imm32/no-outputs
28535     68/push 0/imm32/no-outputs
28536     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
28537     68/push 0x11/imm32/alloc-id:fake
28538     68/push 0/imm32/name
28539     68/push 0/imm32/name
28540     89/<- %ebx 4/r32/esp
28541 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
28542     # primitives->name = "increment"
28543     (copy-array Heap "increment" %ebx)  # Primitive-name
28544 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
28545     # primitives->subx-name = "ff 0/subop/increment"
28546     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
28547     (copy-array Heap "ff 0/subop/increment" %eax)
28548     # convert
28549     c7 0/subop/copy *Curr-block-depth 0/imm32
28550     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
28551     (flush _test-output-buffered-file)
28552 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28558     # check output
28559     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
28560     # . epilogue
28561     89/<- %esp 5/r32/ebp
28562     5d/pop-to-ebp
28563     c3/return
28564 
28565 test-increment-register:
28566     # Select the right register between overloads.
28567     #   foo <- increment
28568     # =>
28569     #   50/increment-eax
28570     #
28571     # There's a variable on the var stack as follows:
28572     #   name: 'foo'
28573     #   type: int
28574     #   register: 'eax'
28575     #
28576     # Primitives are the global definitions.
28577     #
28578     # . prologue
28579     55/push-ebp
28580     89/<- %ebp 4/r32/esp
28581     # setup
28582     (clear-stream _test-output-stream)
28583     (clear-stream $_test-output-buffered-file->buffer)
28584 $test-increment-register:initialize-type:
28585     # var type/ecx: (payload type-tree) = int
28586     68/push 0/imm32/right:null
28587     68/push 0/imm32/right:null
28588     68/push 0/imm32/left:unused
28589     68/push 1/imm32/value:int
28590     68/push 1/imm32/is-atom?:true
28591     68/push 0x11/imm32/alloc-id:fake:payload
28592     89/<- %ecx 4/r32/esp
28593 $test-increment-register:initialize-var:
28594     # var var-foo/ecx: (payload var)
28595     68/push 0/imm32/register
28596     68/push 0/imm32/register
28597     68/push 0/imm32/no-stack-offset
28598     68/push 1/imm32/block-depth
28599     51/push-ecx
28600     68/push 0x11/imm32/alloc-id:fake
28601     68/push 0/imm32/name
28602     68/push 0/imm32/name
28603     68/push 0x11/imm32/alloc-id:fake:payload
28604     89/<- %ecx 4/r32/esp
28605 $test-increment-register:initialize-var-name:
28606     # var-foo->name = "foo"
28607     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28608     (copy-array Heap "foo" %eax)
28609 $test-increment-register:initialize-var-register:
28610     # var-foo->register = "eax"
28611     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28612     (copy-array Heap "eax" %eax)
28613 $test-increment-register:initialize-stmt-var:
28614     # var operand/ebx: (payload stmt-var)
28615     68/push 0/imm32/is-deref:false
28616     68/push 0/imm32/next
28617     68/push 0/imm32/next
28618     51/push-ecx/var-foo
28619     68/push 0x11/imm32/alloc-id:fake
28620     68/push 0x11/imm32/alloc-id:fake:payload
28621     89/<- %ebx 4/r32/esp
28622 $test-increment-register:initialize-stmt:
28623     # var stmt/esi: (addr statement)
28624     53/push-ebx/outputs
28625     68/push 0x11/imm32/alloc-id:fake
28626     68/push 0/imm32/no-inouts
28627     68/push 0/imm32/no-inouts
28628     68/push 0/imm32/operation
28629     68/push 0/imm32/operation
28630     68/push 1/imm32
28631     89/<- %esi 4/r32/esp
28632 $test-increment-register:initialize-stmt-operation:
28633     # stmt->operation = "increment"
28634     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28635     (copy-array Heap "increment" %eax)
28636     # convert
28637     c7 0/subop/copy *Curr-block-depth 0/imm32
28638     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28639     (flush _test-output-buffered-file)
28640 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28646     # check output
28647     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
28648     # . epilogue
28649     89/<- %esp 5/r32/ebp
28650     5d/pop-to-ebp
28651     c3/return
28652 
28653 test-add-reg-to-reg:
28654     #   var1/reg <- add var2/reg
28655     # =>
28656     #   01/add-to %var1 var2
28657     #
28658     # . prologue
28659     55/push-ebp
28660     89/<- %ebp 4/r32/esp
28661     # setup
28662     (clear-stream _test-output-stream)
28663     (clear-stream $_test-output-buffered-file->buffer)
28664 $test-add-reg-to-reg:initialize-type:
28665     # var type/ecx: (payload type-tree) = int
28666     68/push 0/imm32/right:null
28667     68/push 0/imm32/right:null
28668     68/push 0/imm32/left:unused
28669     68/push 1/imm32/value:int
28670     68/push 1/imm32/is-atom?:true
28671     68/push 0x11/imm32/alloc-id:fake:payload
28672     89/<- %ecx 4/r32/esp
28673 $test-add-reg-to-reg:initialize-var1:
28674     # var var1/ecx: (payload var)
28675     68/push 0/imm32/register
28676     68/push 0/imm32/register
28677     68/push 0/imm32/no-stack-offset
28678     68/push 1/imm32/block-depth
28679     51/push-ecx
28680     68/push 0x11/imm32/alloc-id:fake
28681     68/push 0/imm32/name
28682     68/push 0/imm32/name
28683     68/push 0x11/imm32/alloc-id:fake:payload
28684     89/<- %ecx 4/r32/esp
28685 $test-add-reg-to-reg:initialize-var1-name:
28686     # var1->name = "var1"
28687     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28688     (copy-array Heap "var1" %eax)
28689 $test-add-reg-to-reg:initialize-var1-register:
28690     # var1->register = "eax"
28691     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28692     (copy-array Heap "eax" %eax)
28693 $test-add-reg-to-reg:initialize-var2:
28694     # var var2/edx: (payload var)
28695     68/push 0/imm32/register
28696     68/push 0/imm32/register
28697     68/push 0/imm32/no-stack-offset
28698     68/push 1/imm32/block-depth
28699     ff 6/subop/push *(ecx+0x10)
28700     68/push 0x11/imm32/alloc-id:fake
28701     68/push 0/imm32/name
28702     68/push 0/imm32/name
28703     68/push 0x11/imm32/alloc-id:fake:payload
28704     89/<- %edx 4/r32/esp
28705 $test-add-reg-to-reg:initialize-var2-name:
28706     # var2->name = "var2"
28707     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28708     (copy-array Heap "var2" %eax)
28709 $test-add-reg-to-reg:initialize-var2-register:
28710     # var2->register = "ecx"
28711     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
28712     (copy-array Heap "ecx" %eax)
28713 $test-add-reg-to-reg:initialize-inouts:
28714     # var inouts/esi: (payload stmt-var) = [var2]
28715     68/push 0/imm32/is-deref:false
28716     68/push 0/imm32/next
28717     68/push 0/imm32/next
28718     52/push-edx/var2
28719     68/push 0x11/imm32/alloc-id:fake
28720     68/push 0x11/imm32/alloc-id:fake:payload
28721     89/<- %esi 4/r32/esp
28722 $test-add-reg-to-reg:initialize-outputs:
28723     # var outputs/edi: (payload stmt-var) = [var1]
28724     68/push 0/imm32/is-deref:false
28725     68/push 0/imm32/next
28726     68/push 0/imm32/next
28727     51/push-ecx/var1
28728     68/push 0x11/imm32/alloc-id:fake
28729     68/push 0x11/imm32/alloc-id:fake:payload
28730     89/<- %edi 4/r32/esp
28731 $test-add-reg-to-reg:initialize-stmt:
28732     # var stmt/esi: (addr statement)
28733     68/push 0/imm32/next
28734     68/push 0/imm32/next
28735     57/push-edi/outputs
28736     68/push 0x11/imm32/alloc-id:fake
28737     56/push-esi/inouts
28738     68/push 0x11/imm32/alloc-id:fake
28739     68/push 0/imm32/operation
28740     68/push 0/imm32/operation
28741     68/push 1/imm32/tag:stmt1
28742     89/<- %esi 4/r32/esp
28743 $test-add-reg-to-reg:initialize-stmt-operation:
28744     # stmt->operation = "add"
28745     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28746     (copy-array Heap "add" %eax)
28747     # convert
28748     c7 0/subop/copy *Curr-block-depth 0/imm32
28749     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28750     (flush _test-output-buffered-file)
28751 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28757     # check output
28758     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
28759     # . epilogue
28760     89/<- %esp 5/r32/ebp
28761     5d/pop-to-ebp
28762     c3/return
28763 
28764 test-add-reg-to-mem:
28765     #   add-to var1 var2/reg
28766     # =>
28767     #   01/add-to *(ebp+__) var2
28768     #
28769     # . prologue
28770     55/push-ebp
28771     89/<- %ebp 4/r32/esp
28772     # setup
28773     (clear-stream _test-output-stream)
28774     (clear-stream $_test-output-buffered-file->buffer)
28775 $test-add-reg-to-mem:initialize-type:
28776     # var type/ecx: (payload type-tree) = int
28777     68/push 0/imm32/right:null
28778     68/push 0/imm32/right:null
28779     68/push 0/imm32/left:unused
28780     68/push 1/imm32/value:int
28781     68/push 1/imm32/is-atom?:true
28782     68/push 0x11/imm32/alloc-id:fake:payload
28783     89/<- %ecx 4/r32/esp
28784 $test-add-reg-to-mem:initialize-var1:
28785     # var var1/ecx: (payload var)
28786     68/push 0/imm32/register
28787     68/push 0/imm32/register
28788     68/push 8/imm32/stack-offset
28789     68/push 1/imm32/block-depth
28790     51/push-ecx
28791     68/push 0x11/imm32/alloc-id:fake
28792     68/push 0/imm32/name
28793     68/push 0/imm32/name
28794     68/push 0x11/imm32/alloc-id:fake:payload
28795     89/<- %ecx 4/r32/esp
28796 $test-add-reg-to-mem:initialize-var1-name:
28797     # var1->name = "var1"
28798     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28799     (copy-array Heap "var1" %eax)
28800 $test-add-reg-to-mem:initialize-var2:
28801     # var var2/edx: (payload var)
28802     68/push 0/imm32/register
28803     68/push 0/imm32/register
28804     68/push 0/imm32/no-stack-offset
28805     68/push 1/imm32/block-depth
28806     ff 6/subop/push *(ecx+0x10)
28807     68/push 0x11/imm32/alloc-id:fake
28808     68/push 0/imm32/name
28809     68/push 0/imm32/name
28810     68/push 0x11/imm32/alloc-id:fake:payload
28811     89/<- %edx 4/r32/esp
28812 $test-add-reg-to-mem:initialize-var2-name:
28813     # var2->name = "var2"
28814     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28815     (copy-array Heap "var2" %eax)
28816 $test-add-reg-to-mem:initialize-var2-register:
28817     # var2->register = "ecx"
28818     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
28819     (copy-array Heap "ecx" %eax)
28820 $test-add-reg-to-mem:initialize-inouts:
28821     # var inouts/esi: (payload stmt-var) = [var2]
28822     68/push 0/imm32/is-deref:false
28823     68/push 0/imm32/next
28824     68/push 0/imm32/next
28825     52/push-edx/var2
28826     68/push 0x11/imm32/alloc-id:fake
28827     68/push 0x11/imm32/alloc-id:fake:payload
28828     89/<- %esi 4/r32/esp
28829     # inouts = [var1, var2]
28830     68/push 0/imm32/is-deref:false
28831     56/push-esi/next
28832     68/push 0x11/imm32/alloc-id:fake
28833     51/push-ecx/var1
28834     68/push 0x11/imm32/alloc-id:fake
28835     68/push 0x11/imm32/alloc-id:fake:payload
28836     89/<- %esi 4/r32/esp
28837 $test-add-reg-to-mem:initialize-stmt:
28838     # var stmt/esi: (addr statement)
28839     68/push 0/imm32/next
28840     68/push 0/imm32/next
28841     68/push 0/imm32/outputs
28842     68/push 0/imm32/outputs
28843     56/push-esi/inouts
28844     68/push 0x11/imm32/alloc-id:fake
28845     68/push 0/imm32/operation
28846     68/push 0/imm32/operation
28847     68/push 1/imm32/tag:stmt1
28848     89/<- %esi 4/r32/esp
28849 $test-add-reg-to-mem:initialize-stmt-operation:
28850     # stmt->operation = "add-to"
28851     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28852     (copy-array Heap "add-to" %eax)
28853     # convert
28854     c7 0/subop/copy *Curr-block-depth 0/imm32
28855     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28856     (flush _test-output-buffered-file)
28857 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28863     # check output
28864     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
28865     # . epilogue
28866     89/<- %esp 5/r32/ebp
28867     5d/pop-to-ebp
28868     c3/return
28869 
28870 test-add-mem-to-reg:
28871     #   var1/reg <- add var2
28872     # =>
28873     #   03/add *(ebp+__) var1
28874     #
28875     # . prologue
28876     55/push-ebp
28877     89/<- %ebp 4/r32/esp
28878     # setup
28879     (clear-stream _test-output-stream)
28880     (clear-stream $_test-output-buffered-file->buffer)
28881 $test-add-mem-to-reg:initialize-type:
28882     # var type/ecx: (payload type-tree) = int
28883     68/push 0/imm32/right:null
28884     68/push 0/imm32/right:null
28885     68/push 0/imm32/left:unused
28886     68/push 1/imm32/value:int
28887     68/push 1/imm32/is-atom?:true
28888     68/push 0x11/imm32/alloc-id:fake:payload
28889     89/<- %ecx 4/r32/esp
28890 $test-add-mem-to-reg:initialize-var:
28891     # var var1/ecx: (payload var)
28892     68/push 0/imm32/register
28893     68/push 0/imm32/register
28894     68/push 0/imm32/no-stack-offset
28895     68/push 1/imm32/block-depth
28896     51/push-ecx
28897     68/push 0x11/imm32/alloc-id:fake
28898     68/push 0/imm32/name
28899     68/push 0/imm32/name
28900     68/push 0x11/imm32/alloc-id:fake:payload
28901     89/<- %ecx 4/r32/esp
28902 $test-add-mem-to-reg:initialize-var-name:
28903     # var1->name = "foo"
28904     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28905     (copy-array Heap "var1" %eax)
28906 $test-add-mem-to-reg:initialize-var-register:
28907     # var1->register = "eax"
28908     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28909     (copy-array Heap "eax" %eax)
28910 $test-add-mem-to-reg:initialize-var2:
28911     # var var2/edx: (payload var)
28912     68/push 0/imm32/register
28913     68/push 0/imm32/register
28914     68/push 8/imm32/stack-offset
28915     68/push 1/imm32/block-depth
28916     ff 6/subop/push *(ecx+0x10)
28917     68/push 0x11/imm32/alloc-id:fake
28918     68/push 0/imm32/name
28919     68/push 0/imm32/name
28920     68/push 0x11/imm32/alloc-id:fake:payload
28921     89/<- %edx 4/r32/esp
28922 $test-add-mem-to-reg:initialize-var2-name:
28923     # var2->name = "var2"
28924     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28925     (copy-array Heap "var2" %eax)
28926 $test-add-mem-to-reg:initialize-inouts:
28927     # var inouts/esi: (payload stmt-var) = [var2]
28928     68/push 0/imm32/is-deref:false
28929     68/push 0/imm32/next
28930     68/push 0/imm32/next
28931     52/push-edx/var2
28932     68/push 0x11/imm32/alloc-id:fake
28933     68/push 0x11/imm32/alloc-id:fake:payload
28934     89/<- %esi 4/r32/esp
28935 $test-add-mem-to-reg:initialize-outputs:
28936     # var outputs/edi: (payload stmt-var) = [var1]
28937     68/push 0/imm32/is-deref:false
28938     68/push 0/imm32/next
28939     68/push 0/imm32/next
28940     51/push-ecx/var1
28941     68/push 0x11/imm32/alloc-id:fake
28942     68/push 0x11/imm32/alloc-id:fake:payload
28943     89/<- %edi 4/r32/esp
28944 $test-add-mem-to-reg:initialize-stmt:
28945     # var stmt/esi: (addr statement)
28946     68/push 0/imm32/next
28947     68/push 0/imm32/next
28948     57/push-edi/outputs
28949     68/push 0x11/imm32/alloc-id:fake
28950     56/push-esi/inouts
28951     68/push 0x11/imm32/alloc-id:fake
28952     68/push 0/imm32/operation
28953     68/push 0/imm32/operation
28954     68/push 1/imm32/tag:stmt1
28955     89/<- %esi 4/r32/esp
28956 $test-add-mem-to-reg:initialize-stmt-operation:
28957     # stmt->operation = "add"
28958     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28959     (copy-array Heap "add" %eax)
28960     # convert
28961     c7 0/subop/copy *Curr-block-depth 0/imm32
28962     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28963     (flush _test-output-buffered-file)
28964 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
28970     # check output
28971     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
28972     # . epilogue
28973     89/<- %esp 5/r32/ebp
28974     5d/pop-to-ebp
28975     c3/return
28976 
28977 test-add-literal-to-eax:
28978     #   var1/eax <- add 0x34
28979     # =>
28980     #   05/add-to-eax 0x34/imm32
28981     #
28982     # . prologue
28983     55/push-ebp
28984     89/<- %ebp 4/r32/esp
28985     # setup
28986     (clear-stream _test-output-stream)
28987     (clear-stream $_test-output-buffered-file->buffer)
28988 $test-add-literal-to-eax:initialize-var-type:
28989     # var type/ecx: (payload type-tree) = int
28990     68/push 0/imm32/right:null
28991     68/push 0/imm32/right:null
28992     68/push 0/imm32/left:unused
28993     68/push 1/imm32/value:int
28994     68/push 1/imm32/is-atom?:true
28995     68/push 0x11/imm32/alloc-id:fake:payload
28996     89/<- %ecx 4/r32/esp
28997 $test-add-literal-to-eax:initialize-var:
28998     # var v/ecx: (payload var)
28999     68/push 0/imm32/register
29000     68/push 0/imm32/register
29001     68/push 0/imm32/no-stack-offset
29002     68/push 1/imm32/block-depth
29003     51/push-ecx
29004     68/push 0x11/imm32/alloc-id:fake
29005     68/push 0/imm32/name
29006     68/push 0/imm32/name
29007     68/push 0x11/imm32/alloc-id:fake:payload
29008     89/<- %ecx 4/r32/esp
29009 $test-add-literal-to-eax:initialize-var-name:
29010     # v->name = "v"
29011     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29012     (copy-array Heap "v" %eax)
29013 $test-add-literal-to-eax:initialize-var-register:
29014     # v->register = "eax"
29015     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29016     (copy-array Heap "eax" %eax)
29017 $test-add-literal-to-eax:initialize-literal-type:
29018     # var type/edx: (payload type-tree) = literal
29019     68/push 0/imm32/right:null
29020     68/push 0/imm32/right:null
29021     68/push 0/imm32/left:unused
29022     68/push 0/imm32/value:literal
29023     68/push 1/imm32/is-atom?:true
29024     68/push 0x11/imm32/alloc-id:fake:payload
29025     89/<- %edx 4/r32/esp
29026 $test-add-literal-to-eax:initialize-literal:
29027     # var l/edx: (payload var)
29028     68/push 0/imm32/register
29029     68/push 0/imm32/register
29030     68/push 0/imm32/no-stack-offset
29031     68/push 1/imm32/block-depth
29032     52/push-edx
29033     68/push 0x11/imm32/alloc-id:fake
29034     68/push 0/imm32/name
29035     68/push 0/imm32/name
29036     68/push 0x11/imm32/alloc-id:fake:payload
29037     89/<- %edx 4/r32/esp
29038 $test-add-literal-to-eax:initialize-literal-value:
29039     # l->name = "0x34"
29040     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29041     (copy-array Heap "0x34" %eax)
29042 $test-add-literal-to-eax:initialize-inouts:
29043     # var inouts/esi: (payload stmt-var) = [l]
29044     68/push 0/imm32/is-deref:false
29045     68/push 0/imm32/next
29046     68/push 0/imm32/next
29047     52/push-edx/l
29048     68/push 0x11/imm32/alloc-id:fake
29049     68/push 0x11/imm32/alloc-id:fake:payload
29050     89/<- %esi 4/r32/esp
29051 $test-add-literal-to-eax:initialize-outputs:
29052     # var outputs/edi: (payload stmt-var) = [v]
29053     68/push 0/imm32/is-deref:false
29054     68/push 0/imm32/next
29055     68/push 0/imm32/next
29056     51/push-ecx/v
29057     68/push 0x11/imm32/alloc-id:fake
29058     68/push 0x11/imm32/alloc-id:fake:payload
29059     89/<- %edi 4/r32/esp
29060 $test-add-literal-to-eax:initialize-stmt:
29061     # var stmt/esi: (addr statement)
29062     68/push 0/imm32/next
29063     68/push 0/imm32/next
29064     57/push-edi/outputs
29065     68/push 0x11/imm32/alloc-id:fake
29066     56/push-esi/inouts
29067     68/push 0x11/imm32/alloc-id:fake
29068     68/push 0/imm32/operation
29069     68/push 0/imm32/operation
29070     68/push 1/imm32/tag:stmt1
29071     89/<- %esi 4/r32/esp
29072 $test-add-literal-to-eax:initialize-stmt-operation:
29073     # stmt->operation = "add"
29074     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29075     (copy-array Heap "add" %eax)
29076     # convert
29077     c7 0/subop/copy *Curr-block-depth 0/imm32
29078     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29079     (flush _test-output-buffered-file)
29080 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29086     # check output
29087     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
29088     # . epilogue
29089     89/<- %esp 5/r32/ebp
29090     5d/pop-to-ebp
29091     c3/return
29092 
29093 test-add-literal-to-reg:
29094     #   var1/ecx <- add 0x34
29095     # =>
29096     #   81 0/subop/add %ecx 0x34/imm32
29097     #
29098     # . prologue
29099     55/push-ebp
29100     89/<- %ebp 4/r32/esp
29101     # setup
29102     (clear-stream _test-output-stream)
29103     (clear-stream $_test-output-buffered-file->buffer)
29104 $test-add-literal-to-reg:initialize-var-type:
29105     # var type/ecx: (payload type-tree) = int
29106     68/push 0/imm32/right:null
29107     68/push 0/imm32/right:null
29108     68/push 0/imm32/left:unused
29109     68/push 1/imm32/value:int
29110     68/push 1/imm32/is-atom?:true
29111     68/push 0x11/imm32/alloc-id:fake:payload
29112     89/<- %ecx 4/r32/esp
29113 $test-add-literal-to-reg:initialize-var:
29114     # var v/ecx: (payload var)
29115     68/push 0/imm32/register
29116     68/push 0/imm32/register
29117     68/push 0/imm32/no-stack-offset
29118     68/push 1/imm32/block-depth
29119     51/push-ecx
29120     68/push 0x11/imm32/alloc-id:fake
29121     68/push 0/imm32/name
29122     68/push 0/imm32/name
29123     68/push 0x11/imm32/alloc-id:fake:payload
29124     89/<- %ecx 4/r32/esp
29125 $test-add-literal-to-reg:initialize-var-name:
29126     # v->name = "v"
29127     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29128     (copy-array Heap "v" %eax)
29129 $test-add-literal-to-reg:initialize-var-register:
29130     # v->register = "ecx"
29131     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29132     (copy-array Heap "ecx" %eax)
29133 $test-add-literal-to-reg:initialize-literal-type:
29134     # var type/edx: (payload type-tree) = literal
29135     68/push 0/imm32/right:null
29136     68/push 0/imm32/right:null
29137     68/push 0/imm32/left:unused
29138     68/push 0/imm32/value:literal
29139     68/push 1/imm32/is-atom?:true
29140     68/push 0x11/imm32/alloc-id:fake:payload
29141     89/<- %edx 4/r32/esp
29142 $test-add-literal-to-reg:initialize-literal:
29143     # var l/edx: (payload var)
29144     68/push 0/imm32/register
29145     68/push 0/imm32/register
29146     68/push 0/imm32/no-stack-offset
29147     68/push 1/imm32/block-depth
29148     52/push-edx
29149     68/push 0x11/imm32/alloc-id:fake
29150     68/push 0/imm32/name
29151     68/push 0/imm32/name
29152     68/push 0x11/imm32/alloc-id:fake:payload
29153     89/<- %edx 4/r32/esp
29154 $test-add-literal-to-reg:initialize-literal-value:
29155     # l->name = "0x34"
29156     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29157     (copy-array Heap "0x34" %eax)
29158 $test-add-literal-to-reg:initialize-inouts:
29159     # var inouts/esi: (payload stmt-var) = [l]
29160     68/push 0/imm32/is-deref:false
29161     68/push 0/imm32/next
29162     68/push 0/imm32/next
29163     52/push-edx/l
29164     68/push 0x11/imm32/alloc-id:fake
29165     68/push 0x11/imm32/alloc-id:fake:payload
29166     89/<- %esi 4/r32/esp
29167 $test-add-literal-to-reg:initialize-outputs:
29168     # var outputs/edi: (payload stmt-var) = [v]
29169     68/push 0/imm32/is-deref:false
29170     68/push 0/imm32/next
29171     68/push 0/imm32/next
29172     51/push-ecx/v
29173     68/push 0x11/imm32/alloc-id:fake
29174     68/push 0x11/imm32/alloc-id:fake:payload
29175     89/<- %edi 4/r32/esp
29176 $test-add-literal-to-reg:initialize-stmt:
29177     # var stmt/esi: (addr statement)
29178     68/push 0/imm32/next
29179     68/push 0/imm32/next
29180     57/push-edi/outputs
29181     68/push 0x11/imm32/alloc-id:fake
29182     56/push-esi/inouts
29183     68/push 0x11/imm32/alloc-id:fake
29184     68/push 0/imm32/operation
29185     68/push 0/imm32/operation
29186     68/push 1/imm32/tag:stmt1
29187     89/<- %esi 4/r32/esp
29188 $test-add-literal-to-reg:initialize-stmt-operation:
29189     # stmt->operation = "add"
29190     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29191     (copy-array Heap "add" %eax)
29192     # convert
29193     c7 0/subop/copy *Curr-block-depth 0/imm32
29194     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29195     (flush _test-output-buffered-file)
29196 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29202     # check output
29203     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
29204     # . epilogue
29205     89/<- %esp 5/r32/ebp
29206     5d/pop-to-ebp
29207     c3/return
29208 
29209 test-add-literal-to-mem:
29210     #   add-to var1, 0x34
29211     # =>
29212     #   81 0/subop/add %eax 0x34/imm32
29213     #
29214     # . prologue
29215     55/push-ebp
29216     89/<- %ebp 4/r32/esp
29217     # setup
29218     (clear-stream _test-output-stream)
29219     (clear-stream $_test-output-buffered-file->buffer)
29220 $test-add-literal-to-mem:initialize-type:
29221     # var type/ecx: (payload type-tree) = int
29222     68/push 0/imm32/right:null
29223     68/push 0/imm32/right:null
29224     68/push 0/imm32/left:unused
29225     68/push 1/imm32/value:int
29226     68/push 1/imm32/is-atom?:true
29227     68/push 0x11/imm32/alloc-id:fake:payload
29228     89/<- %ecx 4/r32/esp
29229 $test-add-literal-to-mem:initialize-var1:
29230     # var var1/ecx: (payload var)
29231     68/push 0/imm32/register
29232     68/push 0/imm32/register
29233     68/push 8/imm32/stack-offset
29234     68/push 1/imm32/block-depth
29235     51/push-ecx
29236     68/push 0x11/imm32/alloc-id:fake
29237     68/push 0/imm32/name
29238     68/push 0/imm32/name
29239     68/push 0x11/imm32/alloc-id:fake:payload
29240     89/<- %ecx 4/r32/esp
29241 $test-add-literal-to-mem:initialize-var1-name:
29242     # var1->name = "var1"
29243     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29244     (copy-array Heap "var1" %eax)
29245 $test-add-literal-to-mem:initialize-literal-type:
29246     # var type/edx: (payload type-tree) = literal
29247     68/push 0/imm32/right:null
29248     68/push 0/imm32/right:null
29249     68/push 0/imm32/left:unused
29250     68/push 0/imm32/value:literal
29251     68/push 1/imm32/is-atom?:true
29252     68/push 0x11/imm32/alloc-id:fake:payload
29253     89/<- %edx 4/r32/esp
29254 $test-add-literal-to-mem:initialize-literal:
29255     # var l/edx: (payload var)
29256     68/push 0/imm32/register
29257     68/push 0/imm32/register
29258     68/push 0/imm32/no-stack-offset
29259     68/push 1/imm32/block-depth
29260     52/push-edx
29261     68/push 0x11/imm32/alloc-id:fake
29262     68/push 0/imm32/name
29263     68/push 0/imm32/name
29264     68/push 0x11/imm32/alloc-id:fake:payload
29265     89/<- %edx 4/r32/esp
29266 $test-add-literal-to-mem:initialize-literal-value:
29267     # l->name = "0x34"
29268     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29269     (copy-array Heap "0x34" %eax)
29270 $test-add-literal-to-mem:initialize-inouts:
29271     # var inouts/esi: (payload stmt-var) = [l]
29272     68/push 0/imm32/is-deref:false
29273     68/push 0/imm32/next
29274     68/push 0/imm32/next
29275     52/push-edx/l
29276     68/push 0x11/imm32/alloc-id:fake
29277     68/push 0x11/imm32/alloc-id:fake:payload
29278     89/<- %esi 4/r32/esp
29279     # var inouts = (handle stmt-var) = [var1, var2]
29280     68/push 0/imm32/is-deref:false
29281     56/push-esi/next
29282     68/push 0x11/imm32/alloc-id:fake
29283     51/push-ecx/var1
29284     68/push 0x11/imm32/alloc-id:fake
29285     68/push 0x11/imm32/alloc-id:fake:payload
29286     89/<- %esi 4/r32/esp
29287 $test-add-literal-to-mem:initialize-stmt:
29288     # var stmt/esi: (addr statement)
29289     68/push 0/imm32/next
29290     68/push 0/imm32/next
29291     68/push 0/imm32/outputs
29292     68/push 0/imm32/outputs
29293     56/push-esi/inouts
29294     68/push 0x11/imm32/alloc-id:fake
29295     68/push 0/imm32/operation
29296     68/push 0/imm32/operation
29297     68/push 1/imm32/tag:stmt1
29298     89/<- %esi 4/r32/esp
29299 $test-add-literal-to-mem:initialize-stmt-operation:
29300     # stmt->operation = "add-to"
29301     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29302     (copy-array Heap "add-to" %eax)
29303     # convert
29304     c7 0/subop/copy *Curr-block-depth 0/imm32
29305     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29306     (flush _test-output-buffered-file)
29307 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29313     # check output
29314     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
29315     # . epilogue
29316     89/<- %esp 5/r32/ebp
29317     5d/pop-to-ebp
29318     c3/return
29319 
29320 test-shift-reg-by-literal:
29321     #   var1/ecx <- shift-left 2
29322     # =>
29323     #   c1/shift 4/subop/left %ecx 2/imm8
29324     #
29325     # . prologue
29326     55/push-ebp
29327     89/<- %ebp 4/r32/esp
29328     # setup
29329     (clear-stream _test-output-stream)
29330     (clear-stream $_test-output-buffered-file->buffer)
29331 $test-shift-reg-by-literal:initialize-var-type:
29332     # var type/ecx: (payload type-tree) = int
29333     68/push 0/imm32/right:null
29334     68/push 0/imm32/right:null
29335     68/push 0/imm32/left:unused
29336     68/push 1/imm32/value:int
29337     68/push 1/imm32/is-atom?:true
29338     68/push 0x11/imm32/alloc-id:fake:payload
29339     89/<- %ecx 4/r32/esp
29340 $test-shift-reg-by-literal:initialize-var:
29341     # var v/ecx: (payload var)
29342     68/push 0/imm32/register
29343     68/push 0/imm32/register
29344     68/push 0/imm32/no-stack-offset
29345     68/push 1/imm32/block-depth
29346     51/push-ecx
29347     68/push 0x11/imm32/alloc-id:fake
29348     68/push 0/imm32/name
29349     68/push 0/imm32/name
29350     68/push 0x11/imm32/alloc-id:fake:payload
29351     89/<- %ecx 4/r32/esp
29352 $test-shift-reg-by-literal:initialize-var-name:
29353     # v->name = "v"
29354     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29355     (copy-array Heap "v" %eax)
29356 $test-shift-reg-by-literal:initialize-var-register:
29357     # v->register = "ecx"
29358     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29359     (copy-array Heap "ecx" %eax)
29360 $test-shift-reg-by-literal:initialize-literal-type:
29361     # var type/edx: (payload type-tree) = literal
29362     68/push 0/imm32/right:null
29363     68/push 0/imm32/right:null
29364     68/push 0/imm32/left:unused
29365     68/push 0/imm32/value:literal
29366     68/push 1/imm32/is-atom?:true
29367     68/push 0x11/imm32/alloc-id:fake:payload
29368     89/<- %edx 4/r32/esp
29369 $test-shift-reg-by-literal:initialize-literal:
29370     # var l/edx: (payload var)
29371     68/push 0/imm32/register
29372     68/push 0/imm32/register
29373     68/push 0/imm32/no-stack-offset
29374     68/push 1/imm32/block-depth
29375     52/push-edx
29376     68/push 0x11/imm32/alloc-id:fake
29377     68/push 0/imm32/name
29378     68/push 0/imm32/name
29379     68/push 0x11/imm32/alloc-id:fake:payload
29380     89/<- %edx 4/r32/esp
29381 $test-shift-reg-by-literal:initialize-literal-value:
29382     # l->name = "2"
29383     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29384     (copy-array Heap "2" %eax)
29385 $test-shift-reg-by-literal:initialize-inouts:
29386     # var inouts/esi: (payload stmt-var) = [l]
29387     68/push 0/imm32/is-deref:false
29388     68/push 0/imm32/next
29389     68/push 0/imm32/next
29390     52/push-edx/l
29391     68/push 0x11/imm32/alloc-id:fake
29392     68/push 0x11/imm32/alloc-id:fake:payload
29393     89/<- %esi 4/r32/esp
29394 $test-shift-reg-by-literal:initialize-outputs:
29395     # var outputs/edi: (payload stmt-var) = [v]
29396     68/push 0/imm32/is-deref:false
29397     68/push 0/imm32/next
29398     68/push 0/imm32/next
29399     51/push-ecx/v
29400     68/push 0x11/imm32/alloc-id:fake
29401     68/push 0x11/imm32/alloc-id:fake:payload
29402     89/<- %edi 4/r32/esp
29403 $test-shift-reg-by-literal:initialize-stmt:
29404     # var stmt/esi: (addr statement)
29405     68/push 0/imm32/next
29406     68/push 0/imm32/next
29407     57/push-edi/outputs
29408     68/push 0x11/imm32/alloc-id:fake
29409     56/push-esi/inouts
29410     68/push 0x11/imm32/alloc-id:fake
29411     68/push 0/imm32/operation
29412     68/push 0/imm32/operation
29413     68/push 1/imm32/tag:stmt1
29414     89/<- %esi 4/r32/esp
29415 $test-shift-reg-by-literal:initialize-stmt-operation:
29416     # stmt->operation = "shift-left"
29417     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29418     (copy-array Heap "shift-left" %eax)
29419     # convert
29420     c7 0/subop/copy *Curr-block-depth 0/imm32
29421     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29422     (flush _test-output-buffered-file)
29423 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29429     # check output
29430     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
29431     # . epilogue
29432     89/<- %esp 5/r32/ebp
29433     5d/pop-to-ebp
29434     c3/return
29435 
29436 test-shift-mem-by-literal:
29437     #   shift-left var 3
29438     # =>
29439     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
29440     #
29441     # . prologue
29442     55/push-ebp
29443     89/<- %ebp 4/r32/esp
29444     # setup
29445     (clear-stream _test-output-stream)
29446     (clear-stream $_test-output-buffered-file->buffer)
29447 $test-shift-mem-by-literal:initialize-type:
29448     # var type/ecx: (payload type-tree) = int
29449     68/push 0/imm32/right:null
29450     68/push 0/imm32/right:null
29451     68/push 0/imm32/left:unused
29452     68/push 1/imm32/value:int
29453     68/push 1/imm32/is-atom?:true
29454     68/push 0x11/imm32/alloc-id:fake:payload
29455     89/<- %ecx 4/r32/esp
29456 $test-shift-mem-by-literal:initialize-var1:
29457     # var var1/ecx: (payload var)
29458     68/push 0/imm32/register
29459     68/push 0/imm32/register
29460     68/push 8/imm32/stack-offset
29461     68/push 1/imm32/block-depth
29462     51/push-ecx
29463     68/push 0x11/imm32/alloc-id:fake
29464     68/push 0/imm32/name
29465     68/push 0/imm32/name
29466     68/push 0x11/imm32/alloc-id:fake:payload
29467     89/<- %ecx 4/r32/esp
29468 $test-shift-mem-by-literal:initialize-var1-name:
29469     # var1->name = "var1"
29470     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29471     (copy-array Heap "var1" %eax)
29472 $test-shift-mem-by-literal:initialize-literal-type:
29473     # var type/edx: (payload type-tree) = literal
29474     68/push 0/imm32/right:null
29475     68/push 0/imm32/right:null
29476     68/push 0/imm32/left:unused
29477     68/push 0/imm32/value:literal
29478     68/push 1/imm32/is-atom?:true
29479     68/push 0x11/imm32/alloc-id:fake:payload
29480     89/<- %edx 4/r32/esp
29481 $test-shift-mem-by-literal:initialize-literal:
29482     # var l/edx: (payload var)
29483     68/push 0/imm32/register
29484     68/push 0/imm32/register
29485     68/push 0/imm32/no-stack-offset
29486     68/push 1/imm32/block-depth
29487     52/push-edx
29488     68/push 0x11/imm32/alloc-id:fake
29489     68/push 0/imm32/name
29490     68/push 0/imm32/name
29491     68/push 0x11/imm32/alloc-id:fake:payload
29492     89/<- %edx 4/r32/esp
29493 $test-shift-mem-by-literal:initialize-literal-value:
29494     # l->name = "3"
29495     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29496     (copy-array Heap "3" %eax)
29497 $test-shift-mem-by-literal:initialize-inouts:
29498     # var inouts/esi: (payload stmt-var) = [l]
29499     68/push 0/imm32/is-deref:false
29500     68/push 0/imm32/next
29501     68/push 0/imm32/next
29502     52/push-edx/l
29503     68/push 0x11/imm32/alloc-id:fake
29504     68/push 0x11/imm32/alloc-id:fake:payload
29505     89/<- %esi 4/r32/esp
29506     # var inouts = (handle stmt-var) = [var1, var2]
29507     68/push 0/imm32/is-deref:false
29508     56/push-esi/next
29509     68/push 0x11/imm32/alloc-id:fake
29510     51/push-ecx/var1
29511     68/push 0x11/imm32/alloc-id:fake
29512     68/push 0x11/imm32/alloc-id:fake:payload
29513     89/<- %esi 4/r32/esp
29514 $test-shift-mem-by-literal:initialize-stmt:
29515     # var stmt/esi: (addr statement)
29516     68/push 0/imm32/next
29517     68/push 0/imm32/next
29518     68/push 0/imm32/outputs
29519     68/push 0/imm32/outputs
29520     56/push-esi/inouts
29521     68/push 0x11/imm32/alloc-id:fake
29522     68/push 0/imm32/operation
29523     68/push 0/imm32/operation
29524     68/push 1/imm32/tag:stmt1
29525     89/<- %esi 4/r32/esp
29526 $test-shift-mem-by-literal:initialize-stmt-operation:
29527     # stmt->operation = "shift-left"
29528     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29529     (copy-array Heap "shift-left" %eax)
29530     # convert
29531     c7 0/subop/copy *Curr-block-depth 0/imm32
29532     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29533     (flush _test-output-buffered-file)
29534 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29540     # check output
29541     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
29542     # . epilogue
29543     89/<- %esp 5/r32/ebp
29544     5d/pop-to-ebp
29545     c3/return
29546 
29547 test-compare-reg-with-reg:
29548     #   compare var1/ecx, var2/eax
29549     # =>
29550     #   39/compare %ecx 0/r32/eax
29551     #
29552     # . prologue
29553     55/push-ebp
29554     89/<- %ebp 4/r32/esp
29555     # setup
29556     (clear-stream _test-output-stream)
29557     (clear-stream $_test-output-buffered-file->buffer)
29558 $test-compare-reg-with-reg:initialize-type:
29559     # var type/ecx: (payload type-tree) = int
29560     68/push 0/imm32/right:null
29561     68/push 0/imm32/right:null
29562     68/push 0/imm32/left:unused
29563     68/push 1/imm32/value:int
29564     68/push 1/imm32/is-atom?:true
29565     68/push 0x11/imm32/alloc-id:fake:payload
29566     89/<- %ecx 4/r32/esp
29567 $test-compare-reg-with-reg:initialize-var1:
29568     # var var1/ecx: (payload var)
29569     68/push 0/imm32/register
29570     68/push 0/imm32/register
29571     68/push 0/imm32/no-stack-offset
29572     68/push 1/imm32/block-depth
29573     51/push-ecx
29574     68/push 0x11/imm32/alloc-id:fake
29575     68/push 0/imm32/name
29576     68/push 0/imm32/name
29577     68/push 0x11/imm32/alloc-id:fake:payload
29578     89/<- %ecx 4/r32/esp
29579 $test-compare-reg-with-reg:initialize-var1-name:
29580     # var1->name = "var1"
29581     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29582     (copy-array Heap "var1" %eax)
29583 $test-compare-reg-with-reg:initialize-var1-register:
29584     # var1->register = "ecx"
29585     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29586     (copy-array Heap "ecx" %eax)
29587 $test-compare-reg-with-reg:initialize-var2:
29588     # var var2/edx: (payload var)
29589     68/push 0/imm32/register
29590     68/push 0/imm32/register
29591     68/push 0/imm32/no-stack-offset
29592     68/push 1/imm32/block-depth
29593     ff 6/subop/push *(ecx+0x10)
29594     68/push 0x11/imm32/alloc-id:fake
29595     68/push 0/imm32/name
29596     68/push 0/imm32/name
29597     68/push 0x11/imm32/alloc-id:fake:payload
29598     89/<- %edx 4/r32/esp
29599 $test-compare-reg-with-reg:initialize-var2-name:
29600     # var2->name = "var2"
29601     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29602     (copy-array Heap "var2" %eax)
29603 $test-compare-reg-with-reg:initialize-var2-register:
29604     # var2->register = "eax"
29605     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
29606     (copy-array Heap "eax" %eax)
29607 $test-compare-reg-with-reg:initialize-inouts:
29608     # var inouts/esi: (payload stmt-var) = [var2]
29609     68/push 0/imm32/is-deref:false
29610     68/push 0/imm32/next
29611     68/push 0/imm32/next
29612     52/push-edx/var2
29613     68/push 0x11/imm32/alloc-id:fake
29614     68/push 0x11/imm32/alloc-id:fake:payload
29615     89/<- %esi 4/r32/esp
29616     # inouts = [var1, var2]
29617     68/push 0/imm32/is-deref:false
29618     56/push-esi/next
29619     68/push 0x11/imm32/alloc-id:fake
29620     51/push-ecx/var1
29621     68/push 0x11/imm32/alloc-id:fake
29622     68/push 0x11/imm32/alloc-id:fake:payload
29623     89/<- %esi 4/r32/esp
29624 $test-compare-reg-with-reg:initialize-stmt:
29625     # var stmt/esi: (addr statement)
29626     68/push 0/imm32/next
29627     68/push 0/imm32/next
29628     68/push 0/imm32/outputs
29629     68/push 0/imm32/outputs
29630     56/push-esi/inouts
29631     68/push 0x11/imm32/alloc-id:fake
29632     68/push 0/imm32/operation
29633     68/push 0/imm32/operation
29634     68/push 1/imm32/tag:stmt1
29635     89/<- %esi 4/r32/esp
29636 $test-compare-reg-with-reg:initialize-stmt-operation:
29637     # stmt->operation = "compare"
29638     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29639     (copy-array Heap "compare" %eax)
29640     # convert
29641     c7 0/subop/copy *Curr-block-depth 0/imm32
29642     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29643     (flush _test-output-buffered-file)
29644 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29650     # check output
29651     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
29652     # . epilogue
29653     89/<- %esp 5/r32/ebp
29654     5d/pop-to-ebp
29655     c3/return
29656 
29657 test-compare-mem-with-reg:
29658     #   compare var1, var2/eax
29659     # =>
29660     #   39/compare *(ebp+___) 0/r32/eax
29661     #
29662     # . prologue
29663     55/push-ebp
29664     89/<- %ebp 4/r32/esp
29665     # setup
29666     (clear-stream _test-output-stream)
29667     (clear-stream $_test-output-buffered-file->buffer)
29668 $test-compare-mem-with-reg:initialize-type:
29669     # var type/ecx: (payload type-tree) = int
29670     68/push 0/imm32/right:null
29671     68/push 0/imm32/right:null
29672     68/push 0/imm32/left:unused
29673     68/push 1/imm32/value:int
29674     68/push 1/imm32/is-atom?:true
29675     68/push 0x11/imm32/alloc-id:fake:payload
29676     89/<- %ecx 4/r32/esp
29677 $test-compare-mem-with-reg:initialize-var1:
29678     # var var1/ecx: (payload var)
29679     68/push 0/imm32/register
29680     68/push 0/imm32/register
29681     68/push 8/imm32/stack-offset
29682     68/push 1/imm32/block-depth
29683     51/push-ecx
29684     68/push 0x11/imm32/alloc-id:fake
29685     68/push 0/imm32/name
29686     68/push 0/imm32/name
29687     68/push 0x11/imm32/alloc-id:fake:payload
29688     89/<- %ecx 4/r32/esp
29689 $test-compare-mem-with-reg:initialize-var1-name:
29690     # var1->name = "var1"
29691     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29692     (copy-array Heap "var1" %eax)
29693 $test-compare-mem-with-reg:initialize-var2:
29694     # var var2/edx: (payload var)
29695     68/push 0/imm32/register
29696     68/push 0/imm32/register
29697     68/push 0/imm32/no-stack-offset
29698     68/push 1/imm32/block-depth
29699     ff 6/subop/push *(ecx+0x10)
29700     68/push 0x11/imm32/alloc-id:fake
29701     68/push 0/imm32/name
29702     68/push 0/imm32/name
29703     68/push 0x11/imm32/alloc-id:fake:payload
29704     89/<- %edx 4/r32/esp
29705 $test-compare-mem-with-reg:initialize-var2-name:
29706     # var2->name = "var2"
29707     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29708     (copy-array Heap "var2" %eax)
29709 $test-compare-mem-with-reg:initialize-var2-register:
29710     # var2->register = "eax"
29711     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
29712     (copy-array Heap "eax" %eax)
29713 $test-compare-mem-with-reg:initialize-inouts:
29714     # var inouts/esi: (payload stmt-var) = [var2]
29715     68/push 0/imm32/is-deref:false
29716     68/push 0/imm32/next
29717     68/push 0/imm32/next
29718     52/push-edx/var2
29719     68/push 0x11/imm32/alloc-id:fake
29720     68/push 0x11/imm32/alloc-id:fake:payload
29721     89/<- %esi 4/r32/esp
29722     # inouts = [var1, var2]
29723     68/push 0/imm32/is-deref:false
29724     56/push-esi/next
29725     68/push 0x11/imm32/alloc-id:fake
29726     51/push-ecx/var1
29727     68/push 0x11/imm32/alloc-id:fake
29728     68/push 0x11/imm32/alloc-id:fake:payload
29729     89/<- %esi 4/r32/esp
29730 $test-compare-mem-with-reg:initialize-stmt:
29731     # var stmt/esi: (addr statement)
29732     68/push 0/imm32/next
29733     68/push 0/imm32/next
29734     68/push 0/imm32/outputs
29735     68/push 0/imm32/outputs
29736     56/push-esi/inouts
29737     68/push 0x11/imm32/alloc-id:fake
29738     68/push 0/imm32/operation
29739     68/push 0/imm32/operation
29740     68/push 1/imm32/tag:stmt1
29741     89/<- %esi 4/r32/esp
29742 $test-compare-mem-with-reg:initialize-stmt-operation:
29743     # stmt->operation = "compare"
29744     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29745     (copy-array Heap "compare" %eax)
29746     # convert
29747     c7 0/subop/copy *Curr-block-depth 0/imm32
29748     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29749     (flush _test-output-buffered-file)
29750 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29756     # check output
29757     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
29758     # . epilogue
29759     89/<- %esp 5/r32/ebp
29760     5d/pop-to-ebp
29761     c3/return
29762 
29763 test-compare-reg-with-mem:
29764     #   compare var1/eax, var2
29765     # =>
29766     #   3b/compare<- *(ebp+___) 0/r32/eax
29767     #
29768     # . prologue
29769     55/push-ebp
29770     89/<- %ebp 4/r32/esp
29771     # setup
29772     (clear-stream _test-output-stream)
29773     (clear-stream $_test-output-buffered-file->buffer)
29774 $test-compare-reg-with-mem:initialize-type:
29775     # var type/ecx: (payload type-tree) = int
29776     68/push 0/imm32/right:null
29777     68/push 0/imm32/right:null
29778     68/push 0/imm32/left:unused
29779     68/push 1/imm32/value:int
29780     68/push 1/imm32/is-atom?:true
29781     68/push 0x11/imm32/alloc-id:fake:payload
29782     89/<- %ecx 4/r32/esp
29783 $test-compare-reg-with-mem:initialize-var1:
29784     # var var1/ecx: (payload var)
29785     68/push 0/imm32/register
29786     68/push 0/imm32/register
29787     68/push 0/imm32/no-stack-offset
29788     68/push 1/imm32/block-depth
29789     51/push-ecx
29790     68/push 0x11/imm32/alloc-id:fake
29791     68/push 0/imm32/name
29792     68/push 0/imm32/name
29793     68/push 0x11/imm32/alloc-id:fake:payload
29794     89/<- %ecx 4/r32/esp
29795 $test-compare-reg-with-mem:initialize-var1-name:
29796     # var1->name = "var1"
29797     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29798     (copy-array Heap "var1" %eax)
29799 $test-compare-reg-with-mem:initialize-var1-register:
29800     # var1->register = "eax"
29801     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29802     (copy-array Heap "eax" %eax)
29803 $test-compare-reg-with-mem:initialize-var2:
29804     # var var2/edx: (payload var)
29805     68/push 0/imm32/register
29806     68/push 0/imm32/register
29807     68/push 8/imm32/stack-offset
29808     68/push 1/imm32/block-depth
29809     ff 6/subop/push *(ecx+0x10)
29810     68/push 0x11/imm32/alloc-id:fake
29811     68/push 0/imm32/name
29812     68/push 0/imm32/name
29813     68/push 0x11/imm32/alloc-id:fake:payload
29814     89/<- %edx 4/r32/esp
29815 $test-compare-reg-with-mem:initialize-var2-name:
29816     # var2->name = "var2"
29817     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29818     (copy-array Heap "var2" %eax)
29819 $test-compare-reg-with-mem:initialize-inouts:
29820     # var inouts/esi: (payload stmt-var) = [var2]
29821     68/push 0/imm32/is-deref:false
29822     68/push 0/imm32/next
29823     68/push 0/imm32/next
29824     52/push-edx/var2
29825     68/push 0x11/imm32/alloc-id:fake
29826     68/push 0x11/imm32/alloc-id:fake:payload
29827     89/<- %esi 4/r32/esp
29828     # inouts = [var1, var2]
29829     68/push 0/imm32/is-deref:false
29830     56/push-esi/next
29831     68/push 0x11/imm32/alloc-id:fake
29832     51/push-ecx/var1
29833     68/push 0x11/imm32/alloc-id:fake
29834     68/push 0x11/imm32/alloc-id:fake:payload
29835     89/<- %esi 4/r32/esp
29836 $test-compare-reg-with-mem:initialize-stmt:
29837     # var stmt/esi: (addr statement)
29838     68/push 0/imm32/next
29839     68/push 0/imm32/next
29840     68/push 0/imm32/outputs
29841     68/push 0/imm32/outputs
29842     56/push-esi/inouts
29843     68/push 0x11/imm32/alloc-id:fake
29844     68/push 0/imm32/operation
29845     68/push 0/imm32/operation
29846     68/push 1/imm32/tag:stmt1
29847     89/<- %esi 4/r32/esp
29848 $test-compare-reg-with-mem:initialize-stmt-operation:
29849     # stmt->operation = "compare"
29850     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29851     (copy-array Heap "compare" %eax)
29852     # convert
29853     c7 0/subop/copy *Curr-block-depth 0/imm32
29854     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29855     (flush _test-output-buffered-file)
29856 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29862     # check output
29863     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
29864     # . epilogue
29865     89/<- %esp 5/r32/ebp
29866     5d/pop-to-ebp
29867     c3/return
29868 
29869 test-compare-mem-with-literal:
29870     #   compare var1, 0x34
29871     # =>
29872     #   81 7/subop/compare *(ebp+___) 0x34/imm32
29873     #
29874     # . prologue
29875     55/push-ebp
29876     89/<- %ebp 4/r32/esp
29877     # setup
29878     (clear-stream _test-output-stream)
29879     (clear-stream $_test-output-buffered-file->buffer)
29880 $test-compare-mem-with-literal:initialize-type:
29881     # var type/ecx: (payload type-tree) = int
29882     68/push 0/imm32/right:null
29883     68/push 0/imm32/right:null
29884     68/push 0/imm32/left:unused
29885     68/push 1/imm32/value:int
29886     68/push 1/imm32/is-atom?:true
29887     68/push 0x11/imm32/alloc-id:fake:payload
29888     89/<- %ecx 4/r32/esp
29889 $test-compare-mem-with-literal:initialize-var1:
29890     # var var1/ecx: (payload var)
29891     68/push 0/imm32/register
29892     68/push 0/imm32/register
29893     68/push 8/imm32/stack-offset
29894     68/push 1/imm32/block-depth
29895     51/push-ecx
29896     68/push 0x11/imm32/alloc-id:fake
29897     68/push 0/imm32/name
29898     68/push 0/imm32/name
29899     68/push 0x11/imm32/alloc-id:fake:payload
29900     89/<- %ecx 4/r32/esp
29901 $test-compare-mem-with-literal:initialize-var1-name:
29902     # var1->name = "var1"
29903     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29904     (copy-array Heap "var1" %eax)
29905 $test-compare-mem-with-literal:initialize-literal-type:
29906     # var type/edx: (payload type-tree) = literal
29907     68/push 0/imm32/right:null
29908     68/push 0/imm32/right:null
29909     68/push 0/imm32/left:unused
29910     68/push 0/imm32/value:literal
29911     68/push 1/imm32/is-atom?:true
29912     68/push 0x11/imm32/alloc-id:fake:payload
29913     89/<- %edx 4/r32/esp
29914 $test-compare-mem-with-literal:initialize-literal:
29915     # var l/edx: (payload var)
29916     68/push 0/imm32/register
29917     68/push 0/imm32/register
29918     68/push 0/imm32/no-stack-offset
29919     68/push 1/imm32/block-depth
29920     52/push-edx
29921     68/push 0x11/imm32/alloc-id:fake
29922     68/push 0/imm32/name
29923     68/push 0/imm32/name
29924     68/push 0x11/imm32/alloc-id:fake:payload
29925     89/<- %edx 4/r32/esp
29926 $test-compare-mem-with-literal:initialize-literal-value:
29927     # l->name = "0x34"
29928     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29929     (copy-array Heap "0x34" %eax)
29930 $test-compare-mem-with-literal:initialize-inouts:
29931     # var inouts/esi: (payload stmt-var) = [l]
29932     68/push 0/imm32/is-deref:false
29933     68/push 0/imm32/next
29934     68/push 0/imm32/next
29935     52/push-edx/l
29936     68/push 0x11/imm32/alloc-id:fake
29937     68/push 0x11/imm32/alloc-id:fake:payload
29938     89/<- %esi 4/r32/esp
29939     # var inouts = (handle stmt-var) = [var1, var2]
29940     68/push 0/imm32/is-deref:false
29941     56/push-esi/next
29942     68/push 0x11/imm32/alloc-id:fake
29943     51/push-ecx/var1
29944     68/push 0x11/imm32/alloc-id:fake
29945     68/push 0x11/imm32/alloc-id:fake:payload
29946     89/<- %esi 4/r32/esp
29947 $test-compare-mem-with-literal:initialize-stmt:
29948     # var stmt/esi: (addr statement)
29949     68/push 0/imm32/next
29950     68/push 0/imm32/next
29951     68/push 0/imm32/outputs
29952     68/push 0/imm32/outputs
29953     56/push-esi/inouts
29954     68/push 0x11/imm32/alloc-id:fake
29955     68/push 0/imm32/operation
29956     68/push 0/imm32/operation
29957     68/push 1/imm32/tag:stmt1
29958     89/<- %esi 4/r32/esp
29959 $test-compare-mem-with-literal:initialize-stmt-operation:
29960     # stmt->operation = "compare"
29961     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29962     (copy-array Heap "compare" %eax)
29963     # convert
29964     c7 0/subop/copy *Curr-block-depth 0/imm32
29965     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29966     (flush _test-output-buffered-file)
29967 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
29973     # check output
29974     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
29975     # . epilogue
29976     89/<- %esp 5/r32/ebp
29977     5d/pop-to-ebp
29978     c3/return
29979 
29980 test-compare-eax-with-literal:
29981     #   compare var1/eax 0x34
29982     # =>
29983     #   3d/compare-eax-with 0x34/imm32
29984     #
29985     # . prologue
29986     55/push-ebp
29987     89/<- %ebp 4/r32/esp
29988     # setup
29989     (clear-stream _test-output-stream)
29990     (clear-stream $_test-output-buffered-file->buffer)
29991 $test-compare-eax-with-literal:initialize-type:
29992     # var type/ecx: (payload type-tree) = int
29993     68/push 0/imm32/right:null
29994     68/push 0/imm32/right:null
29995     68/push 0/imm32/left:unused
29996     68/push 1/imm32/value:int
29997     68/push 1/imm32/is-atom?:true
29998     68/push 0x11/imm32/alloc-id:fake:payload
29999     89/<- %ecx 4/r32/esp
30000 $test-compare-eax-with-literal:initialize-var1:
30001     # var var1/ecx: (payload var)
30002     68/push 0/imm32/register
30003     68/push 0/imm32/register
30004     68/push 0/imm32/no-stack-offset
30005     68/push 1/imm32/block-depth
30006     51/push-ecx
30007     68/push 0x11/imm32/alloc-id:fake
30008     68/push 0/imm32/name
30009     68/push 0/imm32/name
30010     68/push 0x11/imm32/alloc-id:fake:payload
30011     89/<- %ecx 4/r32/esp
30012 $test-compare-eax-with-literal:initialize-var1-name:
30013     # var1->name = "var1"
30014     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
30015     (copy-array Heap "var1" %eax)
30016 $test-compare-eax-with-literal:initialize-var1-register:
30017     # v->register = "eax"
30018     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
30019     (copy-array Heap "eax" %eax)
30020 $test-compare-eax-with-literal:initialize-literal-type:
30021     # var type/edx: (payload type-tree) = literal
30022     68/push 0/imm32/right:null
30023     68/push 0/imm32/right:null
30024     68/push 0/imm32/left:unused
30025     68/push 0/imm32/value:literal
30026     68/push 1/imm32/is-atom?:true
30027     68/push 0x11/imm32/alloc-id:fake:payload
30028     89/<- %edx 4/r32/esp
30029 $test-compare-eax-with-literal:initialize-literal:
30030     # var l/edx: (payload var)
30031     68/push 0/imm32/register
30032     68/push 0/imm32/register
30033     68/push 0/imm32/no-stack-offset
30034     68/push 1/imm32/block-depth
30035     52/push-edx
30036     68/push 0x11/imm32/alloc-id:fake
30037     68/push 0/imm32/name
30038     68/push 0/imm32/name
30039     68/push 0x11/imm32/alloc-id:fake:payload
30040     89/<- %edx 4/r32/esp
30041 $test-compare-eax-with-literal:initialize-literal-value:
30042     # l->name = "0x34"
30043     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
30044     (copy-array Heap "0x34" %eax)
30045 $test-compare-eax-with-literal:initialize-inouts:
30046     # var inouts/esi: (payload stmt-var) = [l]
30047     68/push 0/imm32/is-deref:false
30048     68/push 0/imm32/next
30049     68/push 0/imm32/next
30050     52/push-edx/l
30051     68/push 0x11/imm32/alloc-id:fake
30052     68/push 0x11/imm32/alloc-id:fake:payload
30053     89/<- %esi 4/r32/esp
30054     # var inouts = (handle stmt-var) = [var1, var2]
30055     68/push 0/imm32/is-deref:false
30056     56/push-esi/next
30057     68/push 0x11/imm32/alloc-id:fake
30058     51/push-ecx/var1
30059     68/push 0x11/imm32/alloc-id:fake
30060     68/push 0x11/imm32/alloc-id:fake:payload
30061     89/<- %esi 4/r32/esp
30062 $test-compare-eax-with-literal:initialize-stmt:
30063     # var stmt/esi: (addr statement)
30064     68/push 0/imm32/next
30065     68/push 0/imm32/next
30066     68/push 0/imm32/outputs
30067     68/push 0/imm32/outputs
30068     56/push-esi/inouts
30069     68/push 0x11/imm32/alloc-id:fake
30070     68/push 0/imm32/operation
30071     68/push 0/imm32/operation
30072     68/push 1/imm32/tag:stmt1
30073     89/<- %esi 4/r32/esp
30074 $test-compare-eax-with-literal:initialize-stmt-operation:
30075     # stmt->operation = "compare"
30076     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
30077     (copy-array Heap "compare" %eax)
30078     # convert
30079     c7 0/subop/copy *Curr-block-depth 0/imm32
30080     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
30081     (flush _test-output-buffered-file)
30082 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
30088     # check output
30089     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
30090     # . epilogue
30091     89/<- %esp 5/r32/ebp
30092     5d/pop-to-ebp
30093     c3/return
30094 
30095 test-compare-reg-with-literal:
30096     #   compare var1/ecx 0x34
30097     # =>
30098     #   81 7/subop/compare %ecx 0x34/imm32
30099     #
30100     # . prologue
30101     55/push-ebp
30102     89/<- %ebp 4/r32/esp
30103     # setup
30104     (clear-stream _test-output-stream)
30105     (clear-stream $_test-output-buffered-file->buffer)
30106 $test-compare-reg-with-literal:initialize-type:
30107     # var type/ecx: (payload type-tree) = int
30108     68/push 0/imm32/right:null
30109     68/push 0/imm32/right:null
30110     68/push 0/imm32/left:unused
30111     68/push 1/imm32/value:int
30112     68/push 1/imm32/is-atom?:true
30113     68/push 0x11/imm32/alloc-id:fake:payload
30114     89/<- %ecx 4/r32/esp
30115 $test-compare-reg-with-literal:initialize-var1:
30116     # var var1/ecx: (payload var)
30117     68/push 0/imm32/register
30118     68/push 0/imm32/register
30119     68/push 0/imm32/no-stack-offset
30120     68/push 1/imm32/block-depth
30121     51/push-ecx
30122     68/push 0x11/imm32/alloc-id:fake
30123     68/push 0/imm32/name
30124     68/push 0/imm32/name
30125     68/push 0x11/imm32/alloc-id:fake:payload
30126     89/<- %ecx 4/r32/esp
30127 $test-compare-reg-with-literal:initialize-var1-name:
30128     # var1->name = "var1"
30129     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
30130     (copy-array Heap "var1" %eax)
30131 $test-compare-reg-with-literal:initialize-var1-register:
30132     # v->register = "ecx"
30133     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
30134     (copy-array Heap "ecx" %eax)
30135 $test-compare-reg-with-literal:initialize-literal-type:
30136     # var type/edx: (payload type-tree) = literal
30137     68/push 0/imm32/right:null
30138     68/push 0/imm32/right:null
30139     68/push 0/imm32/left:unused
30140     68/push 0/imm32/value:literal
30141     68/push 1/imm32/is-atom?:true
30142     68/push 0x11/imm32/alloc-id:fake:payload
30143     89/<- %edx 4/r32/esp
30144 $test-compare-reg-with-literal:initialize-literal:
30145     # var l/edx: (payload var)
30146     68/push 0/imm32/register
30147     68/push 0/imm32/register
30148     68/push 0/imm32/no-stack-offset
30149     68/push 1/imm32/block-depth
30150     52/push-edx
30151     68/push 0x11/imm32/alloc-id:fake
30152     68/push 0/imm32/name
30153     68/push 0/imm32/name
30154     68/push 0x11/imm32/alloc-id:fake:payload
30155     89/<- %edx 4/r32/esp
30156 $test-compare-reg-with-literal:initialize-literal-value:
30157     # l->name = "0x34"
30158     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
30159     (copy-array Heap "0x34" %eax)
30160 $test-compare-reg-with-literal:initialize-inouts:
30161     # var inouts/esi: (payload stmt-var) = [l]
30162     68/push 0/imm32/is-deref:false
30163     68/push 0/imm32/next
30164     68/push 0/imm32/next
30165     52/push-edx/l
30166     68/push 0x11/imm32/alloc-id:fake
30167     68/push 0x11/imm32/alloc-id:fake:payload
30168     89/<- %esi 4/r32/esp
30169     # var inouts = (handle stmt-var) = [var1, var2]
30170     68/push 0/imm32/is-deref:false
30171     56/push-esi/next
30172     68/push 0x11/imm32/alloc-id:fake
30173     51/push-ecx/var1
30174     68/push 0x11/imm32/alloc-id:fake
30175     68/push 0x11/imm32/alloc-id:fake:payload
30176     89/<- %esi 4/r32/esp
30177 $test-compare-reg-with-literal:initialize-stmt:
30178     # var stmt/esi: (addr statement)
30179     68/push 0/imm32/next
30180     68/push 0/imm32/next
30181     68/push 0/imm32/outputs
30182     68/push 0/imm32/outputs
30183     56/push-esi/inouts
30184     68/push 0x11/imm32/alloc-id:fake
30185     68/push 0/imm32/operation
30186     68/push 0/imm32/operation
30187     68/push 1/imm32/tag:stmt1
30188     89/<- %esi 4/r32/esp
30189 $test-compare-reg-with-literal:initialize-stmt-operation:
30190     # stmt->operation = "compare"
30191     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
30192     (copy-array Heap "compare" %eax)
30193     # convert
30194     c7 0/subop/copy *Curr-block-depth 0/imm32
30195     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
30196     (flush _test-output-buffered-file)
30197 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
30203     # check output
30204     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
30205     # . epilogue
30206     89/<- %esp 5/r32/ebp
30207     5d/pop-to-ebp
30208     c3/return
30209 
30210 test-emit-subx-stmt-function-call:
30211     # Call a function on a variable on the stack.
30212     #   f foo
30213     # =>
30214     #   (f *(ebp-8))
30215     # (Changing the function name supports overloading in general, but here it
30216     # just serves to help disambiguate things.)
30217     #
30218     # There's a variable on the var stack as follows:
30219     #   name: 'foo'
30220     #   type: int
30221     #   stack-offset: -8
30222     #
30223     # There's nothing in primitives.
30224     #
30225     # We don't perform any checking here on the type of 'f'.
30226     #
30227     # . prologue
30228     55/push-ebp
30229     89/<- %ebp 4/r32/esp
30230     # setup
30231     (clear-stream _test-output-stream)
30232     (clear-stream $_test-output-buffered-file->buffer)
30233 $test-emit-subx-function-call:initialize-type:
30234     # var type/ecx: (payload type-tree) = int
30235     68/push 0/imm32/right:null
30236     68/push 0/imm32/right:null
30237     68/push 0/imm32/left:unused
30238     68/push 1/imm32/value:int
30239     68/push 1/imm32/is-atom?:true
30240     68/push 0x11/imm32/alloc-id:fake:payload
30241     89/<- %ecx 4/r32/esp
30242 $test-emit-subx-function-call:initialize-var:
30243     # var var-foo/ecx: (payload var) = var(type)
30244     68/push 0/imm32/no-register
30245     68/push 0/imm32/no-register
30246     68/push -8/imm32/stack-offset
30247     68/push 1/imm32/block-depth
30248     51/push-ecx/type
30249     68/push 0x11/imm32/alloc-id:fake
30250     68/push 0/imm32/name
30251     68/push 0/imm32/name
30252     68/push 0x11/imm32/alloc-id:fake:payload
30253     89/<- %ecx 4/r32/esp
30254 $test-emit-subx-function-call:initialize-var-name:
30255     # var-foo->name = "foo"
30256     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
30257     (copy-array Heap "foo" %eax)
30258 $test-emit-subx-function-call:initialize-stmt-var:
30259     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
30260     68/push 0/imm32/is-deref:false
30261     68/push 0/imm32/next
30262     68/push 0/imm32/next
30263     51/push-ecx/var-foo
30264     68/push 0x11/imm32/alloc-id:fake
30265     68/push 0x11/imm32/alloc-id:fake:payload
30266     89/<- %ebx 4/r32/esp
30267 $test-emit-subx-function-call:initialize-stmt:
30268     # var stmt/esi: (addr statement)
30269     68/push 0/imm32/no-outputs
30270     68/push 0/imm32/no-outputs
30271     53/push-ebx/inouts
30272     68/push 0x11/imm32/alloc-id:fake
30273     68/push 0/imm32/operation
30274     68/push 0/imm32/operation
30275     68/push 1/imm32/tag
30276     89/<- %esi 4/r32/esp
30277 $test-emit-subx-function-call:initialize-stmt-operation:
30278     # stmt->operation = "f"
30279     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
30280     (copy-array Heap "f" %eax)
30281     # convert
30282     c7 0/subop/copy *Curr-block-depth 0/imm32
30283     (emit-subx-stmt _test-output-buffered-file %esi 0 Stderr 0)
30284     (flush _test-output-buffered-file)
30285 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
30291     # check output
30292     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
30293     # . epilogue
30294     89/<- %esp 5/r32/ebp
30295     5d/pop-to-ebp
30296     c3/return
30297 
30298 test-emit-subx-stmt-function-call-with-literal-arg:
30299     # Call a function on a literal.
30300     #   f 0x34
30301     # =>
30302     #   (f2 0x34)
30303     #
30304     # . prologue
30305     55/push-ebp
30306     89/<- %ebp 4/r32/esp
30307     # setup
30308     (clear-stream _test-output-stream)
30309     (clear-stream $_test-output-buffered-file->buffer)
30310 $test-emit-subx-function-call-with-literal-arg:initialize-type:
30311     # var type/ecx: (payload type-tree) = int
30312     68/push 0/imm32/right:null
30313     68/push 0/imm32/right:null
30314     68/push 0/imm32/left:unused
30315     68/push 0/imm32/value:literal
30316     68/push 1/imm32/is-atom?:true
30317     68/push 0x11/imm32/alloc-id:fake:payload
30318     89/<- %ecx 4/r32/esp
30319 $test-emit-subx-function-call-with-literal-arg:initialize-var:
30320     # var var-foo/ecx: (payload var) = var(lit)
30321     68/push 0/imm32/no-register
30322     68/push 0/imm32/no-register
30323     68/push 0/imm32/no-stack-offset
30324     68/push 1/imm32/block-depth
30325     51/push-ecx/type
30326     68/push 0x11/imm32/alloc-id:fake
30327     68/push 0/imm32/name
30328     68/push 0/imm32/name
30329     68/push 0x11/imm32/alloc-id:fake:payload
30330     89/<- %ecx 4/r32/esp
30331 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
30332     # var-foo->name = "0x34"
30333     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
30334     (copy-array Heap "0x34" %eax)
30335 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
30336     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
30337     68/push 0/imm32/is-deref:false
30338     68/push 0/imm32/next
30339     68/push 0/imm32/next
30340     51/push-ecx/var-foo
30341     68/push 0x11/imm32/alloc-id:fake
30342     68/push 0x11/imm32/alloc-id:fake:payload
30343     89/<- %ebx 4/r32/esp
30344 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
30345     # var stmt/esi: (addr statement)
30346     68/push 0/imm32/no-outputs
30347     68/push 0/imm32/no-outputs
30348     53/push-ebx/inouts
30349     68/push 0x11/imm32/alloc-id:fake
30350     68/push 0/imm32/operation
30351     68/push 0/imm32/operation
30352     68/push 1/imm32/tag
30353     89/<- %esi 4/r32/esp
30354 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
30355     # stmt->operation = "f"
30356     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
30357     (copy-array Heap "f" %eax)
30358     # convert
30359     c7 0/subop/copy *Curr-block-depth 0/imm32
30360     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx Stderr 0)
30361     (flush _test-output-buffered-file)
30362 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
30368     # check output
30369     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
30370     # . epilogue
30371     89/<- %esp 5/r32/ebp
30372     5d/pop-to-ebp
30373     c3/return
30374 
30375 emit-indent:  # out: (addr buffered-file), n: int
30376     # . prologue
30377     55/push-ebp
30378     89/<- %ebp 4/r32/esp
30379     # . save registers
30380     50/push-eax
30381     # var i/eax: int = n
30382     8b/-> *(ebp+0xc) 0/r32/eax
30383     {
30384       # if (i <= 0) break
30385       3d/compare-eax-with 0/imm32
30386       7e/jump-if-<= break/disp8
30387       (write-buffered *(ebp+8) "  ")
30388       48/decrement-eax
30389       eb/jump loop/disp8
30390     }
30391 $emit-indent:end:
30392     # . restore registers
30393     58/pop-to-eax
30394     # . epilogue
30395     89/<- %esp 5/r32/ebp
30396     5d/pop-to-ebp
30397     c3/return
30398 
30399 emit-subx-prologue:  # out: (addr buffered-file)
30400     # . prologue
30401     55/push-ebp
30402     89/<- %ebp 4/r32/esp
30403     #
30404     (write-buffered *(ebp+8) "  # . prologue\n")
30405     (write-buffered *(ebp+8) "  55/push-ebp\n")
30406     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
30407 $emit-subx-prologue:end:
30408     # . epilogue
30409     89/<- %esp 5/r32/ebp
30410     5d/pop-to-ebp
30411     c3/return
30412 
30413 emit-subx-epilogue:  # out: (addr buffered-file)
30414     # . prologue
30415     55/push-ebp
30416     89/<- %ebp 4/r32/esp
30417     #
30418     (write-buffered *(ebp+8) "  # . epilogue\n")
30419     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
30420     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
30421     (write-buffered *(ebp+8) "  c3/return\n")
30422 $emit-subx-epilogue:end:
30423     # . epilogue
30424     89/<- %esp 5/r32/ebp
30425     5d/pop-to-ebp
30426     c3/return