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 t) <- copy x\n")
 6110     (write _test-input-stream "}\n")
 6111     (write _test-input-stream "type t {\n")
 6112     (write _test-input-stream "  x: int\n")
 6113     (write _test-input-stream "  y: int\n")
 6114     (write _test-input-stream "}\n")
 6115     # convert
 6116     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6117     (flush _test-output-buffered-file)
 6118 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6124     # check output
 6125     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 6126     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 6127     (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")
 6128     (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")
 6129     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 6130     (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")
 6131     # var a: t
 6132     (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")
 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/7")
 6134     # var b/eax: (addr t)
 6135     (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")
 6136     (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")
 6137     # foo a
 6138     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 6139     #
 6140     (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")
 6141     (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")
 6142     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 6143     (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")
 6144     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 6145     (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")
 6146     (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")
 6147     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 6148     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 6149     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 6150     (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")
 6151     (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")
 6152     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 6153     (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")
 6154     (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")
 6155     (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")
 6156     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 6157     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 6158     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 6159     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 6160     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 6161     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32")
 6162     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 6163     # . epilogue
 6164     89/<- %esp 5/r32/ebp
 6165     5d/pop-to-ebp
 6166     c3/return
 6167 
 6168 test-convert-get-on-local-variable:
 6169     # . prologue
 6170     55/push-ebp
 6171     89/<- %ebp 4/r32/esp
 6172     # setup
 6173     (clear-stream _test-input-stream)
 6174     (clear-stream $_test-input-buffered-file->buffer)
 6175     (clear-stream _test-output-stream)
 6176     (clear-stream $_test-output-buffered-file->buffer)
 6177     #
 6178     (write _test-input-stream "fn foo {\n")
 6179     (write _test-input-stream "  var a: t\n")
 6180     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6181     (write _test-input-stream "}\n")
 6182     (write _test-input-stream "type t {\n")
 6183     (write _test-input-stream "  x: int\n")
 6184     (write _test-input-stream "  y: int\n")
 6185     (write _test-input-stream "}\n")
 6186     # convert
 6187     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6188     (flush _test-output-buffered-file)
 6189 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6195     # check output
 6196     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 6197     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 6198     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 6199     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 6200     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 6201     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 6202     # var a
 6203     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 6204     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 6205     # var c
 6206     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 6207     # get
 6208     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 6209     # reclaim c
 6210     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 6211     # reclaim a
 6212     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 6213     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 6214     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 6215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 6216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 6217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 6218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 6219     # . epilogue
 6220     89/<- %esp 5/r32/ebp
 6221     5d/pop-to-ebp
 6222     c3/return
 6223 
 6224 test-convert-get-on-function-argument:
 6225     # . prologue
 6226     55/push-ebp
 6227     89/<- %ebp 4/r32/esp
 6228     # setup
 6229     (clear-stream _test-input-stream)
 6230     (clear-stream $_test-input-buffered-file->buffer)
 6231     (clear-stream _test-output-stream)
 6232     (clear-stream $_test-output-buffered-file->buffer)
 6233     #
 6234     (write _test-input-stream "fn foo a: t {\n")
 6235     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6236     (write _test-input-stream "}\n")
 6237     (write _test-input-stream "type t {\n")
 6238     (write _test-input-stream "  x: int\n")
 6239     (write _test-input-stream "  y: int\n")
 6240     (write _test-input-stream "}\n")
 6241     # convert
 6242     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6243     (flush _test-output-buffered-file)
 6244 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6250     # check output
 6251     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 6252     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 6253     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 6254     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 6255     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 6256     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 6257     # var c
 6258     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 6259     # get
 6260     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 6261     # reclaim c
 6262     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 6263     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 6264     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 6265     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 6266     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 6267     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 6268     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 6269     # . epilogue
 6270     89/<- %esp 5/r32/ebp
 6271     5d/pop-to-ebp
 6272     c3/return
 6273 
 6274 test-convert-get-on-function-argument-with-known-type:
 6275     # . prologue
 6276     55/push-ebp
 6277     89/<- %ebp 4/r32/esp
 6278     # setup
 6279     (clear-stream _test-input-stream)
 6280     (clear-stream $_test-input-buffered-file->buffer)
 6281     (clear-stream _test-output-stream)
 6282     (clear-stream $_test-output-buffered-file->buffer)
 6283     #
 6284     (write _test-input-stream "type t {\n")
 6285     (write _test-input-stream "  x: int\n")
 6286     (write _test-input-stream "  y: int\n")
 6287     (write _test-input-stream "}\n")
 6288     (write _test-input-stream "fn foo a: t {\n")
 6289     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6290     (write _test-input-stream "}\n")
 6291     # convert
 6292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6293     (flush _test-output-buffered-file)
 6294 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6300     # check output
 6301     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 6302     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 6303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 6304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 6305     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 6306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 6307     # var c
 6308     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 6309     # get
 6310     (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")
 6311     # reclaim c
 6312     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 6313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 6314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 6315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 6316     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 6317     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 6318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 6319     # . epilogue
 6320     89/<- %esp 5/r32/ebp
 6321     5d/pop-to-ebp
 6322     c3/return
 6323 
 6324 test-add-with-too-many-inouts:
 6325     # . prologue
 6326     55/push-ebp
 6327     89/<- %ebp 4/r32/esp
 6328     # setup
 6329     (clear-stream _test-input-stream)
 6330     (clear-stream $_test-input-buffered-file->buffer)
 6331     (clear-stream _test-output-stream)
 6332     (clear-stream $_test-output-buffered-file->buffer)
 6333     (clear-stream _test-error-stream)
 6334     (clear-stream $_test-error-buffered-file->buffer)
 6335     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6336     68/push 0/imm32
 6337     68/push 0/imm32
 6338     89/<- %edx 4/r32/esp
 6339     (tailor-exit-descriptor %edx 0x10)
 6340     #
 6341     (write _test-input-stream "fn foo {\n")
 6342     (write _test-input-stream "  var a: int\n")
 6343     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 6344     (write _test-input-stream "}\n")
 6345     # convert
 6346     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6347     # registers except esp clobbered at this point
 6348     # restore ed
 6349     89/<- %edx 4/r32/esp
 6350     (flush _test-output-buffered-file)
 6351     (flush _test-error-buffered-file)
 6352 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6358     # check output
 6359     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 6360     (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")
 6361     # check that stop(1) was called
 6362     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 6363     # don't restore from ebp
 6364     81 0/subop/add %esp 8/imm32
 6365     # . epilogue
 6366     5d/pop-to-ebp
 6367     c3/return
 6368 
 6369 test-add-with-too-many-inouts-2:
 6370     # . prologue
 6371     55/push-ebp
 6372     89/<- %ebp 4/r32/esp
 6373     # setup
 6374     (clear-stream _test-input-stream)
 6375     (clear-stream $_test-input-buffered-file->buffer)
 6376     (clear-stream _test-output-stream)
 6377     (clear-stream $_test-output-buffered-file->buffer)
 6378     (clear-stream _test-error-stream)
 6379     (clear-stream $_test-error-buffered-file->buffer)
 6380     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6381     68/push 0/imm32
 6382     68/push 0/imm32
 6383     89/<- %edx 4/r32/esp
 6384     (tailor-exit-descriptor %edx 0x10)
 6385     #
 6386     (write _test-input-stream "fn foo {\n")
 6387     (write _test-input-stream "  var a: int\n")
 6388     (write _test-input-stream "  add-to a, 0, 1\n")
 6389     (write _test-input-stream "}\n")
 6390     # convert
 6391     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6392     # registers except esp clobbered at this point
 6393     # restore ed
 6394     89/<- %edx 4/r32/esp
 6395     (flush _test-output-buffered-file)
 6396     (flush _test-error-buffered-file)
 6397 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6403     # check output
 6404     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 6405     (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")
 6406     # check that stop(1) was called
 6407     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 6408     # don't restore from ebp
 6409     81 0/subop/add %esp 8/imm32
 6410     # . epilogue
 6411     5d/pop-to-ebp
 6412     c3/return
 6413 
 6414 test-add-with-too-many-outputs:
 6415     # . prologue
 6416     55/push-ebp
 6417     89/<- %ebp 4/r32/esp
 6418     # setup
 6419     (clear-stream _test-input-stream)
 6420     (clear-stream $_test-input-buffered-file->buffer)
 6421     (clear-stream _test-output-stream)
 6422     (clear-stream $_test-output-buffered-file->buffer)
 6423     (clear-stream _test-error-stream)
 6424     (clear-stream $_test-error-buffered-file->buffer)
 6425     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6426     68/push 0/imm32
 6427     68/push 0/imm32
 6428     89/<- %edx 4/r32/esp
 6429     (tailor-exit-descriptor %edx 0x10)
 6430     #
 6431     (write _test-input-stream "fn foo {\n")
 6432     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 6433     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 6434     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 6435     (write _test-input-stream "  c, b <- add a\n")
 6436     (write _test-input-stream "}\n")
 6437     # convert
 6438     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6439     # registers except esp clobbered at this point
 6440     # restore ed
 6441     89/<- %edx 4/r32/esp
 6442     (flush _test-output-buffered-file)
 6443     (flush _test-error-buffered-file)
 6444 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6450     # check output
 6451     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 6452     (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")
 6453     # check that stop(1) was called
 6454     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 6455     # don't restore from ebp
 6456     81 0/subop/add %esp 8/imm32
 6457     # . epilogue
 6458     5d/pop-to-ebp
 6459     c3/return
 6460 
 6461 test-add-with-non-number:
 6462     # . prologue
 6463     55/push-ebp
 6464     89/<- %ebp 4/r32/esp
 6465     # setup
 6466     (clear-stream _test-input-stream)
 6467     (clear-stream $_test-input-buffered-file->buffer)
 6468     (clear-stream _test-output-stream)
 6469     (clear-stream $_test-output-buffered-file->buffer)
 6470     (clear-stream _test-error-stream)
 6471     (clear-stream $_test-error-buffered-file->buffer)
 6472     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6473     68/push 0/imm32
 6474     68/push 0/imm32
 6475     89/<- %edx 4/r32/esp
 6476     (tailor-exit-descriptor %edx 0x10)
 6477     #
 6478     (write _test-input-stream "fn foo {\n")
 6479     (write _test-input-stream "  var a: int\n")
 6480     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 6481     (write _test-input-stream "}\n")
 6482     # convert
 6483     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6484     # registers except esp clobbered at this point
 6485     # restore ed
 6486     89/<- %edx 4/r32/esp
 6487     (flush _test-output-buffered-file)
 6488     (flush _test-error-buffered-file)
 6489 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6495     # check output
 6496     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 6497     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: 'b' must be a non-addr scalar"  "F - test-add-with-non-number: error message")
 6498     # check that stop(1) was called
 6499     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 6500     # don't restore from ebp
 6501     81 0/subop/add %esp 8/imm32
 6502     # . epilogue
 6503     5d/pop-to-ebp
 6504     c3/return
 6505 
 6506 test-add-with-addr-dereferenced:
 6507     # . prologue
 6508     55/push-ebp
 6509     89/<- %ebp 4/r32/esp
 6510     # setup
 6511     (clear-stream _test-input-stream)
 6512     (clear-stream $_test-input-buffered-file->buffer)
 6513     (clear-stream _test-output-stream)
 6514     (clear-stream $_test-output-buffered-file->buffer)
 6515     #
 6516     (write _test-input-stream "fn foo {\n")
 6517     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 6518     (write _test-input-stream "  add-to *a, 1\n")
 6519     (write _test-input-stream "}\n")
 6520     # convert
 6521     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6522     (flush _test-output-buffered-file)
 6523     # no error
 6524     # . epilogue
 6525     89/<- %esp 5/r32/ebp
 6526     5d/pop-to-ebp
 6527     c3/return
 6528 
 6529 test-copy-with-no-inout:
 6530     # . prologue
 6531     55/push-ebp
 6532     89/<- %ebp 4/r32/esp
 6533     # setup
 6534     (clear-stream _test-input-stream)
 6535     (clear-stream $_test-input-buffered-file->buffer)
 6536     (clear-stream _test-output-stream)
 6537     (clear-stream $_test-output-buffered-file->buffer)
 6538     (clear-stream _test-error-stream)
 6539     (clear-stream $_test-error-buffered-file->buffer)
 6540     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6541     68/push 0/imm32
 6542     68/push 0/imm32
 6543     89/<- %edx 4/r32/esp
 6544     (tailor-exit-descriptor %edx 0x10)
 6545     #
 6546     (write _test-input-stream "fn foo {\n")
 6547     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 6548     (write _test-input-stream "}\n")
 6549     # convert
 6550     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6551     # registers except esp clobbered at this point
 6552     # restore ed
 6553     89/<- %edx 4/r32/esp
 6554     (flush _test-output-buffered-file)
 6555     (flush _test-error-buffered-file)
 6556 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6562     # check output
 6563     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 6564     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 6565     # check that stop(1) was called
 6566     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 6567     # don't restore from ebp
 6568     81 0/subop/add %esp 8/imm32
 6569     # . epilogue
 6570     5d/pop-to-ebp
 6571     c3/return
 6572 
 6573 test-copy-with-multiple-inouts:
 6574     # . prologue
 6575     55/push-ebp
 6576     89/<- %ebp 4/r32/esp
 6577     # setup
 6578     (clear-stream _test-input-stream)
 6579     (clear-stream $_test-input-buffered-file->buffer)
 6580     (clear-stream _test-output-stream)
 6581     (clear-stream $_test-output-buffered-file->buffer)
 6582     (clear-stream _test-error-stream)
 6583     (clear-stream $_test-error-buffered-file->buffer)
 6584     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6585     68/push 0/imm32
 6586     68/push 0/imm32
 6587     89/<- %edx 4/r32/esp
 6588     (tailor-exit-descriptor %edx 0x10)
 6589     #
 6590     (write _test-input-stream "fn foo {\n")
 6591     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 6592     (write _test-input-stream "}\n")
 6593     # convert
 6594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6595     # registers except esp clobbered at this point
 6596     # restore ed
 6597     89/<- %edx 4/r32/esp
 6598     (flush _test-output-buffered-file)
 6599     (flush _test-error-buffered-file)
 6600 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6606     # check output
 6607     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 6608     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one inout"  "F - test-copy-with-multiple-inouts: error message")
 6609     # check that stop(1) was called
 6610     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 6611     # don't restore from ebp
 6612     81 0/subop/add %esp 8/imm32
 6613     # . epilogue
 6614     5d/pop-to-ebp
 6615     c3/return
 6616 
 6617 test-copy-with-no-output:
 6618     # . prologue
 6619     55/push-ebp
 6620     89/<- %ebp 4/r32/esp
 6621     # setup
 6622     (clear-stream _test-input-stream)
 6623     (clear-stream $_test-input-buffered-file->buffer)
 6624     (clear-stream _test-output-stream)
 6625     (clear-stream $_test-output-buffered-file->buffer)
 6626     (clear-stream _test-error-stream)
 6627     (clear-stream $_test-error-buffered-file->buffer)
 6628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6629     68/push 0/imm32
 6630     68/push 0/imm32
 6631     89/<- %edx 4/r32/esp
 6632     (tailor-exit-descriptor %edx 0x10)
 6633     #
 6634     (write _test-input-stream "fn foo {\n")
 6635     (write _test-input-stream "  copy 0\n")
 6636     (write _test-input-stream "}\n")
 6637     # convert
 6638     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6639     # registers except esp clobbered at this point
 6640     # restore ed
 6641     89/<- %edx 4/r32/esp
 6642     (flush _test-output-buffered-file)
 6643     (flush _test-error-buffered-file)
 6644 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6650     # check output
 6651     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 6652     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 6653     # check that stop(1) was called
 6654     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 6655     # don't restore from ebp
 6656     81 0/subop/add %esp 8/imm32
 6657     # . epilogue
 6658     5d/pop-to-ebp
 6659     c3/return
 6660 
 6661 test-copy-with-multiple-outputs:
 6662     # . prologue
 6663     55/push-ebp
 6664     89/<- %ebp 4/r32/esp
 6665     # setup
 6666     (clear-stream _test-input-stream)
 6667     (clear-stream $_test-input-buffered-file->buffer)
 6668     (clear-stream _test-output-stream)
 6669     (clear-stream $_test-output-buffered-file->buffer)
 6670     (clear-stream _test-error-stream)
 6671     (clear-stream $_test-error-buffered-file->buffer)
 6672     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6673     68/push 0/imm32
 6674     68/push 0/imm32
 6675     89/<- %edx 4/r32/esp
 6676     (tailor-exit-descriptor %edx 0x10)
 6677     #
 6678     (write _test-input-stream "fn foo {\n")
 6679     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 6680     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 6681     (write _test-input-stream "  x, y <- copy 0\n")
 6682     (write _test-input-stream "}\n")
 6683     # convert
 6684     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6685     # registers except esp clobbered at this point
 6686     # restore ed
 6687     89/<- %edx 4/r32/esp
 6688     (flush _test-output-buffered-file)
 6689     (flush _test-error-buffered-file)
 6690 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6696     # check output
 6697     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 6698     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one output"  "F - test-copy-with-multiple-outputs: error message")
 6699     # check that stop(1) was called
 6700     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 6701     # don't restore from ebp
 6702     81 0/subop/add %esp 8/imm32
 6703     # . epilogue
 6704     5d/pop-to-ebp
 6705     c3/return
 6706 
 6707 test-copy-invalid-value-to-address:
 6708     # . prologue
 6709     55/push-ebp
 6710     89/<- %ebp 4/r32/esp
 6711     # setup
 6712     (clear-stream _test-input-stream)
 6713     (clear-stream $_test-input-buffered-file->buffer)
 6714     (clear-stream _test-output-stream)
 6715     (clear-stream $_test-output-buffered-file->buffer)
 6716     (clear-stream _test-error-stream)
 6717     (clear-stream $_test-error-buffered-file->buffer)
 6718     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6719     68/push 0/imm32
 6720     68/push 0/imm32
 6721     89/<- %edx 4/r32/esp
 6722     (tailor-exit-descriptor %edx 0x10)
 6723     #
 6724     (write _test-input-stream "fn foo {\n")
 6725     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 6726     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 6727     (write _test-input-stream "}\n")
 6728     # convert
 6729     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6730     # registers except esp clobbered at this point
 6731     # restore ed
 6732     89/<- %edx 4/r32/esp
 6733     (flush _test-output-buffered-file)
 6734     (flush _test-error-buffered-file)
 6735 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6741     # check output
 6742     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 6743     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr scalar"  "F - test-copy-invalid-value-to-address: error message")
 6744     # check that stop(1) was called
 6745     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 6746     # don't restore from ebp
 6747     81 0/subop/add %esp 8/imm32
 6748     # . epilogue
 6749     5d/pop-to-ebp
 6750     c3/return
 6751 
 6752 test-copy-deref-address:
 6753     # . prologue
 6754     55/push-ebp
 6755     89/<- %ebp 4/r32/esp
 6756     # setup
 6757     (clear-stream _test-input-stream)
 6758     (clear-stream $_test-input-buffered-file->buffer)
 6759     (clear-stream _test-output-stream)
 6760     (clear-stream $_test-output-buffered-file->buffer)
 6761     #
 6762     (write _test-input-stream "fn foo {\n")
 6763     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 6764     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 6765     (write _test-input-stream "}\n")
 6766     # convert
 6767     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6768     (flush _test-output-buffered-file)
 6769 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6775     # not bothering checking output
 6776     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-deref-address: error message")
 6777     # . epilogue
 6778     5d/pop-to-ebp
 6779     c3/return
 6780 
 6781 test-copy-to-non-register:
 6782     # . prologue
 6783     55/push-ebp
 6784     89/<- %ebp 4/r32/esp
 6785     # setup
 6786     (clear-stream _test-input-stream)
 6787     (clear-stream $_test-input-buffered-file->buffer)
 6788     (clear-stream _test-output-stream)
 6789     (clear-stream $_test-output-buffered-file->buffer)
 6790     (clear-stream _test-error-stream)
 6791     (clear-stream $_test-error-buffered-file->buffer)
 6792     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6793     68/push 0/imm32
 6794     68/push 0/imm32
 6795     89/<- %edx 4/r32/esp
 6796     (tailor-exit-descriptor %edx 0x10)
 6797     #
 6798     (write _test-input-stream "fn foo {\n")
 6799     (write _test-input-stream "  var x: int\n")
 6800     (write _test-input-stream "  x <- copy 0\n")
 6801     (write _test-input-stream "}\n")
 6802     # convert
 6803     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6804     # registers except esp clobbered at this point
 6805     # restore ed
 6806     89/<- %edx 4/r32/esp
 6807     (flush _test-output-buffered-file)
 6808     (flush _test-error-buffered-file)
 6809 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6815     # check output
 6816     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 6817     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: output 'x' not in a register"  "F - test-copy-to-non-register: error message")
 6818     # check that stop(1) was called
 6819     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 6820     # don't restore from ebp
 6821     81 0/subop/add %esp 8/imm32
 6822     # . epilogue
 6823     5d/pop-to-ebp
 6824     c3/return
 6825 
 6826 test-copy-non-scalar:
 6827     # . prologue
 6828     55/push-ebp
 6829     89/<- %ebp 4/r32/esp
 6830     # setup
 6831     (clear-stream _test-input-stream)
 6832     (clear-stream $_test-input-buffered-file->buffer)
 6833     (clear-stream _test-output-stream)
 6834     (clear-stream $_test-output-buffered-file->buffer)
 6835     (clear-stream _test-error-stream)
 6836     (clear-stream $_test-error-buffered-file->buffer)
 6837     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6838     68/push 0/imm32
 6839     68/push 0/imm32
 6840     89/<- %edx 4/r32/esp
 6841     (tailor-exit-descriptor %edx 0x10)
 6842     #
 6843     (write _test-input-stream "fn foo {\n")
 6844     (write _test-input-stream "  var x: (handle int)\n")
 6845     (write _test-input-stream "  var y/eax: int <- copy x\n")
 6846     (write _test-input-stream "}\n")
 6847     # convert
 6848     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6849     # registers except esp clobbered at this point
 6850     # restore ed
 6851     89/<- %edx 4/r32/esp
 6852     (flush _test-output-buffered-file)
 6853     (flush _test-error-buffered-file)
 6854 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6860     # check output
 6861     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-scalar: output should be empty")
 6862     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-non-scalar: error message")
 6863     # check that stop(1) was called
 6864     (check-ints-equal *(edx+4) 2 "F - test-copy-non-scalar: exit status")
 6865     # don't restore from ebp
 6866     81 0/subop/add %esp 8/imm32
 6867     # . epilogue
 6868     5d/pop-to-ebp
 6869     c3/return
 6870 
 6871 test-copy-to-with-no-inout:
 6872     # . prologue
 6873     55/push-ebp
 6874     89/<- %ebp 4/r32/esp
 6875     # setup
 6876     (clear-stream _test-input-stream)
 6877     (clear-stream $_test-input-buffered-file->buffer)
 6878     (clear-stream _test-output-stream)
 6879     (clear-stream $_test-output-buffered-file->buffer)
 6880     (clear-stream _test-error-stream)
 6881     (clear-stream $_test-error-buffered-file->buffer)
 6882     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6883     68/push 0/imm32
 6884     68/push 0/imm32
 6885     89/<- %edx 4/r32/esp
 6886     (tailor-exit-descriptor %edx 0x10)
 6887     #
 6888     (write _test-input-stream "fn foo {\n")
 6889     (write _test-input-stream "  copy-to\n")
 6890     (write _test-input-stream "}\n")
 6891     # convert
 6892     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6893     # registers except esp clobbered at this point
 6894     # restore ed
 6895     89/<- %edx 4/r32/esp
 6896     (flush _test-output-buffered-file)
 6897     (flush _test-error-buffered-file)
 6898 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6904     # check output
 6905     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 6906     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-inout: error message")
 6907     # check that stop(1) was called
 6908     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 6909     # don't restore from ebp
 6910     81 0/subop/add %esp 8/imm32
 6911     # . epilogue
 6912     5d/pop-to-ebp
 6913     c3/return
 6914 
 6915 test-copy-to-with-no-input:
 6916     # . prologue
 6917     55/push-ebp
 6918     89/<- %ebp 4/r32/esp
 6919     # setup
 6920     (clear-stream _test-input-stream)
 6921     (clear-stream $_test-input-buffered-file->buffer)
 6922     (clear-stream _test-output-stream)
 6923     (clear-stream $_test-output-buffered-file->buffer)
 6924     (clear-stream _test-error-stream)
 6925     (clear-stream $_test-error-buffered-file->buffer)
 6926     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6927     68/push 0/imm32
 6928     68/push 0/imm32
 6929     89/<- %edx 4/r32/esp
 6930     (tailor-exit-descriptor %edx 0x10)
 6931     #
 6932     (write _test-input-stream "fn foo {\n")
 6933     (write _test-input-stream "  var x: boolean\n")
 6934     (write _test-input-stream "  copy-to x\n")
 6935     (write _test-input-stream "}\n")
 6936     # convert
 6937     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6938     # registers except esp clobbered at this point
 6939     # restore ed
 6940     89/<- %edx 4/r32/esp
 6941     (flush _test-output-buffered-file)
 6942     (flush _test-error-buffered-file)
 6943 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6949     # check output
 6950     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-input: output should be empty")
 6951     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-input: error message")
 6952     # check that stop(1) was called
 6953     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-input: exit status")
 6954     # don't restore from ebp
 6955     81 0/subop/add %esp 8/imm32
 6956     # . epilogue
 6957     5d/pop-to-ebp
 6958     c3/return
 6959 
 6960 test-copy-to-with-no-register:
 6961     # . prologue
 6962     55/push-ebp
 6963     89/<- %ebp 4/r32/esp
 6964     # setup
 6965     (clear-stream _test-input-stream)
 6966     (clear-stream $_test-input-buffered-file->buffer)
 6967     (clear-stream _test-output-stream)
 6968     (clear-stream $_test-output-buffered-file->buffer)
 6969     (clear-stream _test-error-stream)
 6970     (clear-stream $_test-error-buffered-file->buffer)
 6971     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6972     68/push 0/imm32
 6973     68/push 0/imm32
 6974     89/<- %edx 4/r32/esp
 6975     (tailor-exit-descriptor %edx 0x10)
 6976     #
 6977     (write _test-input-stream "fn foo {\n")
 6978     (write _test-input-stream "  var x: boolean\n")
 6979     (write _test-input-stream "  copy-to x, x\n")
 6980     (write _test-input-stream "}\n")
 6981     # convert
 6982     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6983     # registers except esp clobbered at this point
 6984     # restore ed
 6985     89/<- %edx 4/r32/esp
 6986     (flush _test-output-buffered-file)
 6987     (flush _test-error-buffered-file)
 6988 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6994     # check output
 6995     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 6996     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-with-no-register: error message")
 6997     # check that stop(1) was called
 6998     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 6999     # don't restore from ebp
 7000     81 0/subop/add %esp 8/imm32
 7001     # . epilogue
 7002     5d/pop-to-ebp
 7003     c3/return
 7004 
 7005 test-copy-to-with-too-many-inouts:
 7006     # . prologue
 7007     55/push-ebp
 7008     89/<- %ebp 4/r32/esp
 7009     # setup
 7010     (clear-stream _test-input-stream)
 7011     (clear-stream $_test-input-buffered-file->buffer)
 7012     (clear-stream _test-output-stream)
 7013     (clear-stream $_test-output-buffered-file->buffer)
 7014     (clear-stream _test-error-stream)
 7015     (clear-stream $_test-error-buffered-file->buffer)
 7016     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7017     68/push 0/imm32
 7018     68/push 0/imm32
 7019     89/<- %edx 4/r32/esp
 7020     (tailor-exit-descriptor %edx 0x10)
 7021     #
 7022     (write _test-input-stream "fn foo {\n")
 7023     (write _test-input-stream "  var x: boolean\n")
 7024     (write _test-input-stream "  copy-to x, 0, 0\n")
 7025     (write _test-input-stream "}\n")
 7026     # convert
 7027     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7028     # registers except esp clobbered at this point
 7029     # restore ed
 7030     89/<- %edx 4/r32/esp
 7031     (flush _test-output-buffered-file)
 7032     (flush _test-error-buffered-file)
 7033 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7039     # check output
 7040     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 7041     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-too-many-inouts: error message")
 7042     # check that stop(1) was called
 7043     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 7044     # don't restore from ebp
 7045     81 0/subop/add %esp 8/imm32
 7046     # . epilogue
 7047     5d/pop-to-ebp
 7048     c3/return
 7049 
 7050 test-copy-to-with-output:
 7051     # . prologue
 7052     55/push-ebp
 7053     89/<- %ebp 4/r32/esp
 7054     # setup
 7055     (clear-stream _test-input-stream)
 7056     (clear-stream $_test-input-buffered-file->buffer)
 7057     (clear-stream _test-output-stream)
 7058     (clear-stream $_test-output-buffered-file->buffer)
 7059     (clear-stream _test-error-stream)
 7060     (clear-stream $_test-error-buffered-file->buffer)
 7061     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7062     68/push 0/imm32
 7063     68/push 0/imm32
 7064     89/<- %edx 4/r32/esp
 7065     (tailor-exit-descriptor %edx 0x10)
 7066     #
 7067     (write _test-input-stream "fn foo {\n")
 7068     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7069     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7070     (write _test-input-stream "  x <- copy-to y, 0\n")
 7071     (write _test-input-stream "}\n")
 7072     # convert
 7073     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7074     # registers except esp clobbered at this point
 7075     # restore ed
 7076     89/<- %edx 4/r32/esp
 7077     (flush _test-output-buffered-file)
 7078     (flush _test-error-buffered-file)
 7079 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7085     # check output
 7086     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 7087     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must not have any outputs"  "F - test-copy-to-with-output: error message")
 7088     # check that stop(1) was called
 7089     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 7090     # don't restore from ebp
 7091     81 0/subop/add %esp 8/imm32
 7092     # . epilogue
 7093     5d/pop-to-ebp
 7094     c3/return
 7095 
 7096 test-copy-to-invalid-value-to-address:
 7097     # . prologue
 7098     55/push-ebp
 7099     89/<- %ebp 4/r32/esp
 7100     # setup
 7101     (clear-stream _test-input-stream)
 7102     (clear-stream $_test-input-buffered-file->buffer)
 7103     (clear-stream _test-output-stream)
 7104     (clear-stream $_test-output-buffered-file->buffer)
 7105     (clear-stream _test-error-stream)
 7106     (clear-stream $_test-error-buffered-file->buffer)
 7107     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7108     68/push 0/imm32
 7109     68/push 0/imm32
 7110     89/<- %edx 4/r32/esp
 7111     (tailor-exit-descriptor %edx 0x10)
 7112     #
 7113     (write _test-input-stream "fn foo {\n")
 7114     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7115     (write _test-input-stream "  var y: (addr int)\n")
 7116     (write _test-input-stream "  copy-to y, x\n")
 7117     (write _test-input-stream "}\n")
 7118     # convert
 7119     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7120     # registers except esp clobbered at this point
 7121     # restore ed
 7122     89/<- %edx 4/r32/esp
 7123     (flush _test-output-buffered-file)
 7124     (flush _test-error-buffered-file)
 7125 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7131     # check output
 7132     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 7133     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr scalar"  "F - test-copy-to-invalid-value-to-address: error message")
 7134     # check that stop(1) was called
 7135     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 7136     # don't restore from ebp
 7137     81 0/subop/add %esp 8/imm32
 7138     # . epilogue
 7139     5d/pop-to-ebp
 7140     c3/return
 7141 
 7142 test-copy-to-deref-address:
 7143     # . prologue
 7144     55/push-ebp
 7145     89/<- %ebp 4/r32/esp
 7146     # setup
 7147     (clear-stream _test-input-stream)
 7148     (clear-stream $_test-input-buffered-file->buffer)
 7149     (clear-stream _test-output-stream)
 7150     (clear-stream $_test-output-buffered-file->buffer)
 7151     #
 7152     (write _test-input-stream "fn foo {\n")
 7153     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7154     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 7155     (write _test-input-stream "  copy-to *y, x\n")
 7156     (write _test-input-stream "}\n")
 7157     # convert
 7158     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7159     (flush _test-output-buffered-file)
 7160 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7166     # not bothering checking output
 7167     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-to-deref-address: error message")
 7168     # . epilogue
 7169     5d/pop-to-ebp
 7170     c3/return
 7171 
 7172 test-copy-to-non-scalar:
 7173     # . prologue
 7174     55/push-ebp
 7175     89/<- %ebp 4/r32/esp
 7176     # setup
 7177     (clear-stream _test-input-stream)
 7178     (clear-stream $_test-input-buffered-file->buffer)
 7179     (clear-stream _test-output-stream)
 7180     (clear-stream $_test-output-buffered-file->buffer)
 7181     (clear-stream _test-error-stream)
 7182     (clear-stream $_test-error-buffered-file->buffer)
 7183     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7184     68/push 0/imm32
 7185     68/push 0/imm32
 7186     89/<- %edx 4/r32/esp
 7187     (tailor-exit-descriptor %edx 0x10)
 7188     #
 7189     (write _test-input-stream "fn foo {\n")
 7190     (write _test-input-stream "  var x: (handle int)\n")
 7191     (write _test-input-stream "  var y: int\n")
 7192     (write _test-input-stream "  copy-to y, x\n")
 7193     (write _test-input-stream "}\n")
 7194     # convert
 7195     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7196     # registers except esp clobbered at this point
 7197     # restore ed
 7198     89/<- %edx 4/r32/esp
 7199     (flush _test-output-buffered-file)
 7200     (flush _test-error-buffered-file)
 7201 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7207     # check output
 7208     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-scalar: output should be empty")
 7209 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-non-scalar: error message")
 7210     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-non-scalar: error message")
 7211     # check that stop(1) was called
 7212     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-scalar: exit status")
 7213     # don't restore from ebp
 7214     81 0/subop/add %esp 8/imm32
 7215     # . epilogue
 7216     5d/pop-to-ebp
 7217     c3/return
 7218 
 7219 test-compare-with-no-inout:
 7220     # . prologue
 7221     55/push-ebp
 7222     89/<- %ebp 4/r32/esp
 7223     # setup
 7224     (clear-stream _test-input-stream)
 7225     (clear-stream $_test-input-buffered-file->buffer)
 7226     (clear-stream _test-output-stream)
 7227     (clear-stream $_test-output-buffered-file->buffer)
 7228     (clear-stream _test-error-stream)
 7229     (clear-stream $_test-error-buffered-file->buffer)
 7230     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7231     68/push 0/imm32
 7232     68/push 0/imm32
 7233     89/<- %edx 4/r32/esp
 7234     (tailor-exit-descriptor %edx 0x10)
 7235     #
 7236     (write _test-input-stream "fn foo {\n")
 7237     (write _test-input-stream "  var x: boolean\n")
 7238     (write _test-input-stream "  compare\n")
 7239     (write _test-input-stream "}\n")
 7240     # convert
 7241     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7242     # registers except esp clobbered at this point
 7243     # restore ed
 7244     89/<- %edx 4/r32/esp
 7245     (flush _test-output-buffered-file)
 7246     (flush _test-error-buffered-file)
 7247 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7253     # check output
 7254     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 7255     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 7256     # check that stop(1) was called
 7257     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 7258     # don't restore from ebp
 7259     81 0/subop/add %esp 8/imm32
 7260     # . epilogue
 7261     5d/pop-to-ebp
 7262     c3/return
 7263 
 7264 test-compare-with-no-input:
 7265     # . prologue
 7266     55/push-ebp
 7267     89/<- %ebp 4/r32/esp
 7268     # setup
 7269     (clear-stream _test-input-stream)
 7270     (clear-stream $_test-input-buffered-file->buffer)
 7271     (clear-stream _test-output-stream)
 7272     (clear-stream $_test-output-buffered-file->buffer)
 7273     (clear-stream _test-error-stream)
 7274     (clear-stream $_test-error-buffered-file->buffer)
 7275     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7276     68/push 0/imm32
 7277     68/push 0/imm32
 7278     89/<- %edx 4/r32/esp
 7279     (tailor-exit-descriptor %edx 0x10)
 7280     #
 7281     (write _test-input-stream "fn foo {\n")
 7282     (write _test-input-stream "  var x: boolean\n")
 7283     (write _test-input-stream "  compare x\n")
 7284     (write _test-input-stream "}\n")
 7285     # convert
 7286     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7287     # registers except esp clobbered at this point
 7288     # restore ed
 7289     89/<- %edx 4/r32/esp
 7290     (flush _test-output-buffered-file)
 7291     (flush _test-error-buffered-file)
 7292 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7298     # check output
 7299     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-input: output should be empty")
 7300     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-input: error message")
 7301     # check that stop(1) was called
 7302     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-input: exit status")
 7303     # don't restore from ebp
 7304     81 0/subop/add %esp 8/imm32
 7305     # . epilogue
 7306     5d/pop-to-ebp
 7307     c3/return
 7308 
 7309 test-compare-with-too-many-inouts:
 7310     # . prologue
 7311     55/push-ebp
 7312     89/<- %ebp 4/r32/esp
 7313     # setup
 7314     (clear-stream _test-input-stream)
 7315     (clear-stream $_test-input-buffered-file->buffer)
 7316     (clear-stream _test-output-stream)
 7317     (clear-stream $_test-output-buffered-file->buffer)
 7318     (clear-stream _test-error-stream)
 7319     (clear-stream $_test-error-buffered-file->buffer)
 7320     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7321     68/push 0/imm32
 7322     68/push 0/imm32
 7323     89/<- %edx 4/r32/esp
 7324     (tailor-exit-descriptor %edx 0x10)
 7325     #
 7326     (write _test-input-stream "fn foo {\n")
 7327     (write _test-input-stream "  var x: boolean\n")
 7328     (write _test-input-stream "  compare x, 0, 0\n")
 7329     (write _test-input-stream "}\n")
 7330     # convert
 7331     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7332     # registers except esp clobbered at this point
 7333     # restore ed
 7334     89/<- %edx 4/r32/esp
 7335     (flush _test-output-buffered-file)
 7336     (flush _test-error-buffered-file)
 7337 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7343     # check output
 7344     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 7345     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-too-many-inouts: error message")
 7346     # check that stop(1) was called
 7347     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 7348     # don't restore from ebp
 7349     81 0/subop/add %esp 8/imm32
 7350     # . epilogue
 7351     5d/pop-to-ebp
 7352     c3/return
 7353 
 7354 test-compare-with-output:
 7355     # . prologue
 7356     55/push-ebp
 7357     89/<- %ebp 4/r32/esp
 7358     # setup
 7359     (clear-stream _test-input-stream)
 7360     (clear-stream $_test-input-buffered-file->buffer)
 7361     (clear-stream _test-output-stream)
 7362     (clear-stream $_test-output-buffered-file->buffer)
 7363     (clear-stream _test-error-stream)
 7364     (clear-stream $_test-error-buffered-file->buffer)
 7365     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7366     68/push 0/imm32
 7367     68/push 0/imm32
 7368     89/<- %edx 4/r32/esp
 7369     (tailor-exit-descriptor %edx 0x10)
 7370     #
 7371     (write _test-input-stream "fn foo {\n")
 7372     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7373     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7374     (write _test-input-stream "  x <- compare y, 0\n")
 7375     (write _test-input-stream "}\n")
 7376     # convert
 7377     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7378     # registers except esp clobbered at this point
 7379     # restore ed
 7380     89/<- %edx 4/r32/esp
 7381     (flush _test-output-buffered-file)
 7382     (flush _test-error-buffered-file)
 7383 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7389     # check output
 7390     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 7391     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 7392     # check that stop(1) was called
 7393     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 7394     # don't restore from ebp
 7395     81 0/subop/add %esp 8/imm32
 7396     # . epilogue
 7397     5d/pop-to-ebp
 7398     c3/return
 7399 
 7400 test-compare-invalid-value-to-address:
 7401     # . prologue
 7402     55/push-ebp
 7403     89/<- %ebp 4/r32/esp
 7404     # setup
 7405     (clear-stream _test-input-stream)
 7406     (clear-stream $_test-input-buffered-file->buffer)
 7407     (clear-stream _test-output-stream)
 7408     (clear-stream $_test-output-buffered-file->buffer)
 7409     (clear-stream _test-error-stream)
 7410     (clear-stream $_test-error-buffered-file->buffer)
 7411     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7412     68/push 0/imm32
 7413     68/push 0/imm32
 7414     89/<- %edx 4/r32/esp
 7415     (tailor-exit-descriptor %edx 0x10)
 7416     #
 7417     (write _test-input-stream "fn foo {\n")
 7418     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7419     (write _test-input-stream "  var y: (addr int)\n")
 7420     (write _test-input-stream "  compare y, x\n")
 7421     (write _test-input-stream "}\n")
 7422     # convert
 7423     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7424     # registers except esp clobbered at this point
 7425     # restore ed
 7426     89/<- %edx 4/r32/esp
 7427     (flush _test-output-buffered-file)
 7428     (flush _test-error-buffered-file)
 7429 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7435     # check output
 7436     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 7437     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'y' must be a non-addr scalar"  "F - test-compare-invalid-value-to-address: error message")
 7438     # check that stop(1) was called
 7439     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 7440     # don't restore from ebp
 7441     81 0/subop/add %esp 8/imm32
 7442     # . epilogue
 7443     5d/pop-to-ebp
 7444     c3/return
 7445 
 7446 test-compare-address:
 7447     # . prologue
 7448     55/push-ebp
 7449     89/<- %ebp 4/r32/esp
 7450     # setup
 7451     (clear-stream _test-input-stream)
 7452     (clear-stream $_test-input-buffered-file->buffer)
 7453     (clear-stream _test-output-stream)
 7454     (clear-stream $_test-output-buffered-file->buffer)
 7455     #
 7456     (write _test-input-stream "fn foo {\n")
 7457     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7458     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7459     (write _test-input-stream "  compare y, x\n")
 7460     (write _test-input-stream "}\n")
 7461     # convert
 7462     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7463     (flush _test-output-buffered-file)
 7464 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7470     # not bothering checking output
 7471     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-address: error message")
 7472     # . epilogue
 7473     5d/pop-to-ebp
 7474     c3/return
 7475 
 7476 test-compare-deref-address:
 7477     # . prologue
 7478     55/push-ebp
 7479     89/<- %ebp 4/r32/esp
 7480     # setup
 7481     (clear-stream _test-input-stream)
 7482     (clear-stream $_test-input-buffered-file->buffer)
 7483     (clear-stream _test-output-stream)
 7484     (clear-stream $_test-output-buffered-file->buffer)
 7485     #
 7486     (write _test-input-stream "fn foo {\n")
 7487     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7488     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 7489     (write _test-input-stream "  compare *y, x\n")
 7490     (write _test-input-stream "}\n")
 7491     # convert
 7492     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7493     (flush _test-output-buffered-file)
 7494 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7500     # not bothering checking output
 7501     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-deref-address: error message")
 7502     # . epilogue
 7503     5d/pop-to-ebp
 7504     c3/return
 7505 
 7506 test-compare-two-vars-in-memory:
 7507     # . prologue
 7508     55/push-ebp
 7509     89/<- %ebp 4/r32/esp
 7510     # setup
 7511     (clear-stream _test-input-stream)
 7512     (clear-stream $_test-input-buffered-file->buffer)
 7513     (clear-stream _test-output-stream)
 7514     (clear-stream $_test-output-buffered-file->buffer)
 7515     (clear-stream _test-error-stream)
 7516     (clear-stream $_test-error-buffered-file->buffer)
 7517     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7518     68/push 0/imm32
 7519     68/push 0/imm32
 7520     89/<- %edx 4/r32/esp
 7521     (tailor-exit-descriptor %edx 0x10)
 7522     #
 7523     (write _test-input-stream "fn foo {\n")
 7524     (write _test-input-stream "  var x: boolean\n")
 7525     (write _test-input-stream "  compare x, x\n")
 7526     (write _test-input-stream "}\n")
 7527     # convert
 7528     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7529     # registers except esp clobbered at this point
 7530     # restore ed
 7531     89/<- %edx 4/r32/esp
 7532     (flush _test-output-buffered-file)
 7533     (flush _test-error-buffered-file)
 7534 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7540     # check output
 7541     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 7542     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-two-vars-in-memory: error message")
 7543     # check that stop(1) was called
 7544     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 7545     # don't restore from ebp
 7546     81 0/subop/add %esp 8/imm32
 7547     # . epilogue
 7548     5d/pop-to-ebp
 7549     c3/return
 7550 
 7551 test-compare-non-scalar:
 7552     # . prologue
 7553     55/push-ebp
 7554     89/<- %ebp 4/r32/esp
 7555     # setup
 7556     (clear-stream _test-input-stream)
 7557     (clear-stream $_test-input-buffered-file->buffer)
 7558     (clear-stream _test-output-stream)
 7559     (clear-stream $_test-output-buffered-file->buffer)
 7560     (clear-stream _test-error-stream)
 7561     (clear-stream $_test-error-buffered-file->buffer)
 7562     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7563     68/push 0/imm32
 7564     68/push 0/imm32
 7565     89/<- %edx 4/r32/esp
 7566     (tailor-exit-descriptor %edx 0x10)
 7567     #
 7568     (write _test-input-stream "fn foo {\n")
 7569     (write _test-input-stream "  var x: (handle int)\n")
 7570     (write _test-input-stream "  var y: int\n")
 7571     (write _test-input-stream "  compare y, x\n")
 7572     (write _test-input-stream "}\n")
 7573     # convert
 7574     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7575     # registers except esp clobbered at this point
 7576     # restore ed
 7577     89/<- %edx 4/r32/esp
 7578     (flush _test-output-buffered-file)
 7579     (flush _test-error-buffered-file)
 7580 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7586     # check output
 7587     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 7588 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'x' is too large to compare"  "F - test-compare-non-scalar: error message")
 7589     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 7590     # check that stop(1) was called
 7591     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 7592     # don't restore from ebp
 7593     81 0/subop/add %esp 8/imm32
 7594     # . epilogue
 7595     5d/pop-to-ebp
 7596     c3/return
 7597 
 7598 test-address-with-no-inout:
 7599     # . prologue
 7600     55/push-ebp
 7601     89/<- %ebp 4/r32/esp
 7602     # setup
 7603     (clear-stream _test-input-stream)
 7604     (clear-stream $_test-input-buffered-file->buffer)
 7605     (clear-stream _test-output-stream)
 7606     (clear-stream $_test-output-buffered-file->buffer)
 7607     (clear-stream _test-error-stream)
 7608     (clear-stream $_test-error-buffered-file->buffer)
 7609     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7610     68/push 0/imm32
 7611     68/push 0/imm32
 7612     89/<- %edx 4/r32/esp
 7613     (tailor-exit-descriptor %edx 0x10)
 7614     #
 7615     (write _test-input-stream "fn foo {\n")
 7616     (write _test-input-stream "  var x/eax: boolean <- address\n")
 7617     (write _test-input-stream "}\n")
 7618     # convert
 7619     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7620     # registers except esp clobbered at this point
 7621     # restore ed
 7622     89/<- %edx 4/r32/esp
 7623     (flush _test-output-buffered-file)
 7624     (flush _test-error-buffered-file)
 7625 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7631     # check output
 7632     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 7633     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 7634     # check that stop(1) was called
 7635     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 7636     # don't restore from ebp
 7637     81 0/subop/add %esp 8/imm32
 7638     # . epilogue
 7639     5d/pop-to-ebp
 7640     c3/return
 7641 
 7642 test-address-with-multiple-inouts:
 7643     # . prologue
 7644     55/push-ebp
 7645     89/<- %ebp 4/r32/esp
 7646     # setup
 7647     (clear-stream _test-input-stream)
 7648     (clear-stream $_test-input-buffered-file->buffer)
 7649     (clear-stream _test-output-stream)
 7650     (clear-stream $_test-output-buffered-file->buffer)
 7651     (clear-stream _test-error-stream)
 7652     (clear-stream $_test-error-buffered-file->buffer)
 7653     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7654     68/push 0/imm32
 7655     68/push 0/imm32
 7656     89/<- %edx 4/r32/esp
 7657     (tailor-exit-descriptor %edx 0x10)
 7658     #
 7659     (write _test-input-stream "fn foo {\n")
 7660     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 7661     (write _test-input-stream "}\n")
 7662     # convert
 7663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7664     # registers except esp clobbered at this point
 7665     # restore ed
 7666     89/<- %edx 4/r32/esp
 7667     (flush _test-output-buffered-file)
 7668     (flush _test-error-buffered-file)
 7669 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7675     # check output
 7676     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 7677     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one inout"  "F - test-address-with-multiple-inouts: error message")
 7678     # check that stop(1) was called
 7679     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 7680     # don't restore from ebp
 7681     81 0/subop/add %esp 8/imm32
 7682     # . epilogue
 7683     5d/pop-to-ebp
 7684     c3/return
 7685 
 7686 test-address-with-no-output:
 7687     # . prologue
 7688     55/push-ebp
 7689     89/<- %ebp 4/r32/esp
 7690     # setup
 7691     (clear-stream _test-input-stream)
 7692     (clear-stream $_test-input-buffered-file->buffer)
 7693     (clear-stream _test-output-stream)
 7694     (clear-stream $_test-output-buffered-file->buffer)
 7695     (clear-stream _test-error-stream)
 7696     (clear-stream $_test-error-buffered-file->buffer)
 7697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7698     68/push 0/imm32
 7699     68/push 0/imm32
 7700     89/<- %edx 4/r32/esp
 7701     (tailor-exit-descriptor %edx 0x10)
 7702     #
 7703     (write _test-input-stream "fn foo {\n")
 7704     (write _test-input-stream "  address 0\n")
 7705     (write _test-input-stream "}\n")
 7706     # convert
 7707     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7708     # registers except esp clobbered at this point
 7709     # restore ed
 7710     89/<- %edx 4/r32/esp
 7711     (flush _test-output-buffered-file)
 7712     (flush _test-error-buffered-file)
 7713 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7719     # check output
 7720     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 7721     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 7722     # check that stop(1) was called
 7723     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 7724     # don't restore from ebp
 7725     81 0/subop/add %esp 8/imm32
 7726     # . epilogue
 7727     5d/pop-to-ebp
 7728     c3/return
 7729 
 7730 test-address-with-multiple-outputs:
 7731     # . prologue
 7732     55/push-ebp
 7733     89/<- %ebp 4/r32/esp
 7734     # setup
 7735     (clear-stream _test-input-stream)
 7736     (clear-stream $_test-input-buffered-file->buffer)
 7737     (clear-stream _test-output-stream)
 7738     (clear-stream $_test-output-buffered-file->buffer)
 7739     (clear-stream _test-error-stream)
 7740     (clear-stream $_test-error-buffered-file->buffer)
 7741     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7742     68/push 0/imm32
 7743     68/push 0/imm32
 7744     89/<- %edx 4/r32/esp
 7745     (tailor-exit-descriptor %edx 0x10)
 7746     #
 7747     (write _test-input-stream "fn foo {\n")
 7748     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7749     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7750     (write _test-input-stream "  x, y <- address 0\n")
 7751     (write _test-input-stream "}\n")
 7752     # convert
 7753     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7754     # registers except esp clobbered at this point
 7755     # restore ed
 7756     89/<- %edx 4/r32/esp
 7757     (flush _test-output-buffered-file)
 7758     (flush _test-error-buffered-file)
 7759 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7765     # check output
 7766     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 7767     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one output"  "F - test-address-with-multiple-outputs: error message")
 7768     # check that stop(1) was called
 7769     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 7770     # don't restore from ebp
 7771     81 0/subop/add %esp 8/imm32
 7772     # . epilogue
 7773     5d/pop-to-ebp
 7774     c3/return
 7775 
 7776 # silly but it works
 7777 test-address-of-deref:
 7778     # . prologue
 7779     55/push-ebp
 7780     89/<- %ebp 4/r32/esp
 7781     # setup
 7782     (clear-stream _test-input-stream)
 7783     (clear-stream $_test-input-buffered-file->buffer)
 7784     (clear-stream _test-output-stream)
 7785     (clear-stream $_test-output-buffered-file->buffer)
 7786     #
 7787     (write _test-input-stream "fn foo {\n")
 7788     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7789     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 7790     (write _test-input-stream "}\n")
 7791     # convert
 7792     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7793     (flush _test-output-buffered-file)
 7794 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7800     # not bothering checking output
 7801     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-of-deref: error message")
 7802     # . epilogue
 7803     5d/pop-to-ebp
 7804     c3/return
 7805 
 7806 test-address-to-non-register:
 7807     # . prologue
 7808     55/push-ebp
 7809     89/<- %ebp 4/r32/esp
 7810     # setup
 7811     (clear-stream _test-input-stream)
 7812     (clear-stream $_test-input-buffered-file->buffer)
 7813     (clear-stream _test-output-stream)
 7814     (clear-stream $_test-output-buffered-file->buffer)
 7815     (clear-stream _test-error-stream)
 7816     (clear-stream $_test-error-buffered-file->buffer)
 7817     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7818     68/push 0/imm32
 7819     68/push 0/imm32
 7820     89/<- %edx 4/r32/esp
 7821     (tailor-exit-descriptor %edx 0x10)
 7822     #
 7823     (write _test-input-stream "fn foo {\n")
 7824     (write _test-input-stream "  var x: (addr int)\n")
 7825     (write _test-input-stream "  x <- address 0\n")
 7826     (write _test-input-stream "}\n")
 7827     # convert
 7828     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7829     # registers except esp clobbered at this point
 7830     # restore ed
 7831     89/<- %edx 4/r32/esp
 7832     (flush _test-output-buffered-file)
 7833     (flush _test-error-buffered-file)
 7834 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7840     # check output
 7841     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 7842     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'x' not in a register"  "F - test-address-to-non-register: error message")
 7843     # check that stop(1) was called
 7844     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 7845     # don't restore from ebp
 7846     81 0/subop/add %esp 8/imm32
 7847     # . epilogue
 7848     5d/pop-to-ebp
 7849     c3/return
 7850 
 7851 test-address-with-wrong-type:
 7852     # . prologue
 7853     55/push-ebp
 7854     89/<- %ebp 4/r32/esp
 7855     # setup
 7856     (clear-stream _test-input-stream)
 7857     (clear-stream $_test-input-buffered-file->buffer)
 7858     (clear-stream _test-output-stream)
 7859     (clear-stream $_test-output-buffered-file->buffer)
 7860     (clear-stream _test-error-stream)
 7861     (clear-stream $_test-error-buffered-file->buffer)
 7862     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7863     68/push 0/imm32
 7864     68/push 0/imm32
 7865     89/<- %edx 4/r32/esp
 7866     (tailor-exit-descriptor %edx 0x10)
 7867     #
 7868     (write _test-input-stream "fn foo {\n")
 7869     (write _test-input-stream "  var x: int\n")
 7870     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 7871     (write _test-input-stream "}\n")
 7872     # convert
 7873     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7874     # registers except esp clobbered at this point
 7875     # restore ed
 7876     89/<- %edx 4/r32/esp
 7877     (flush _test-output-buffered-file)
 7878     (flush _test-error-buffered-file)
 7879 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7885     # check output
 7886     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 7887     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'y' cannot hold address of 'x'"  "F - test-address-with-wrong-type: error message")
 7888     # check that stop(1) was called
 7889     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 7890     # don't restore from ebp
 7891     81 0/subop/add %esp 8/imm32
 7892     # . epilogue
 7893     5d/pop-to-ebp
 7894     c3/return
 7895 
 7896 test-address-with-right-type-for-array:
 7897     # . prologue
 7898     55/push-ebp
 7899     89/<- %ebp 4/r32/esp
 7900     # setup
 7901     (clear-stream _test-input-stream)
 7902     (clear-stream $_test-input-buffered-file->buffer)
 7903     (clear-stream _test-output-stream)
 7904     (clear-stream $_test-output-buffered-file->buffer)
 7905     #
 7906     (write _test-input-stream "fn foo {\n")
 7907     (write _test-input-stream "  var x: (array int 3)\n")
 7908     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 7909     (write _test-input-stream "}\n")
 7910     # convert
 7911     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7912     (flush _test-output-buffered-file)
 7913 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7919     # no error
 7920     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-array: error message")
 7921     # don't bother checking output
 7922     # . epilogue
 7923     89/<- %esp 5/r32/ebp
 7924     5d/pop-to-ebp
 7925     c3/return
 7926 
 7927 test-address-with-right-type-for-stream:
 7928     # . prologue
 7929     55/push-ebp
 7930     89/<- %ebp 4/r32/esp
 7931     # setup
 7932     (clear-stream _test-input-stream)
 7933     (clear-stream $_test-input-buffered-file->buffer)
 7934     (clear-stream _test-output-stream)
 7935     (clear-stream $_test-output-buffered-file->buffer)
 7936     #
 7937     (write _test-input-stream "fn foo {\n")
 7938     (write _test-input-stream "  var x: (stream int 3)\n")
 7939     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 7940     (write _test-input-stream "}\n")
 7941     # convert
 7942     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7943     (flush _test-output-buffered-file)
 7944 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7950     # no error
 7951     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-stream: error message")
 7952     # don't bother checking output
 7953     # . epilogue
 7954     89/<- %esp 5/r32/ebp
 7955     5d/pop-to-ebp
 7956     c3/return
 7957 
 7958 test-get-with-wrong-field:
 7959     # . prologue
 7960     55/push-ebp
 7961     89/<- %ebp 4/r32/esp
 7962     # setup
 7963     (clear-stream _test-input-stream)
 7964     (clear-stream $_test-input-buffered-file->buffer)
 7965     (clear-stream _test-output-stream)
 7966     (clear-stream $_test-output-buffered-file->buffer)
 7967     (clear-stream _test-error-stream)
 7968     (clear-stream $_test-error-buffered-file->buffer)
 7969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7970     68/push 0/imm32
 7971     68/push 0/imm32
 7972     89/<- %edx 4/r32/esp
 7973     (tailor-exit-descriptor %edx 0x10)
 7974     #
 7975     (write _test-input-stream "fn foo {\n")
 7976     (write _test-input-stream "  var a: t\n")
 7977     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7978     (write _test-input-stream "}\n")
 7979     (write _test-input-stream "type t {\n")
 7980     (write _test-input-stream "  x: int\n")
 7981     (write _test-input-stream "}\n")
 7982     # convert
 7983     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7984     # registers except esp clobbered at this point
 7985     # restore ed
 7986     89/<- %edx 4/r32/esp
 7987     (flush _test-output-buffered-file)
 7988     (flush _test-error-buffered-file)
 7989 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7995     # check output
 7996     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 7997     (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")
 7998     # check that stop(1) was called
 7999     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 8000     # don't restore from ebp
 8001     81 0/subop/add %esp 8/imm32
 8002     # . epilogue
 8003     5d/pop-to-ebp
 8004     c3/return
 8005 
 8006 test-get-with-wrong-base-type:
 8007     # . prologue
 8008     55/push-ebp
 8009     89/<- %ebp 4/r32/esp
 8010     # setup
 8011     (clear-stream _test-input-stream)
 8012     (clear-stream $_test-input-buffered-file->buffer)
 8013     (clear-stream _test-output-stream)
 8014     (clear-stream $_test-output-buffered-file->buffer)
 8015     (clear-stream _test-error-stream)
 8016     (clear-stream $_test-error-buffered-file->buffer)
 8017     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8018     68/push 0/imm32
 8019     68/push 0/imm32
 8020     89/<- %edx 4/r32/esp
 8021     (tailor-exit-descriptor %edx 0x10)
 8022     #
 8023     (write _test-input-stream "fn foo {\n")
 8024     (write _test-input-stream "  var a: int\n")
 8025     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8026     (write _test-input-stream "}\n")
 8027     # convert
 8028     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8029     # registers except esp clobbered at this point
 8030     # restore ed
 8031     89/<- %edx 4/r32/esp
 8032     (flush _test-output-buffered-file)
 8033     (flush _test-error-buffered-file)
 8034 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8040     # check output
 8041     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 8042     (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")
 8043     # check that stop(1) was called
 8044     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 8045     # don't restore from ebp
 8046     81 0/subop/add %esp 8/imm32
 8047     # . epilogue
 8048     5d/pop-to-ebp
 8049     c3/return
 8050 
 8051 test-get-with-wrong-base-type-2:
 8052     # . prologue
 8053     55/push-ebp
 8054     89/<- %ebp 4/r32/esp
 8055     # setup
 8056     (clear-stream _test-input-stream)
 8057     (clear-stream $_test-input-buffered-file->buffer)
 8058     (clear-stream _test-output-stream)
 8059     (clear-stream $_test-output-buffered-file->buffer)
 8060     (clear-stream _test-error-stream)
 8061     (clear-stream $_test-error-buffered-file->buffer)
 8062     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8063     68/push 0/imm32
 8064     68/push 0/imm32
 8065     89/<- %edx 4/r32/esp
 8066     (tailor-exit-descriptor %edx 0x10)
 8067     #
 8068     (write _test-input-stream "fn foo {\n")
 8069     (write _test-input-stream "  var a: (addr t)\n")
 8070     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8071     (write _test-input-stream "}\n")
 8072     (write _test-input-stream "type t {\n")
 8073     (write _test-input-stream "  x: int\n")
 8074     (write _test-input-stream "}\n")
 8075     # convert
 8076     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8077     # registers except esp clobbered at this point
 8078     # restore ed
 8079     89/<- %edx 4/r32/esp
 8080     (flush _test-output-buffered-file)
 8081     (flush _test-error-buffered-file)
 8082 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8088     # check output
 8089     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 8090     (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")
 8091     # check that stop(1) was called
 8092     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 8093     # don't restore from ebp
 8094     81 0/subop/add %esp 8/imm32
 8095     # . epilogue
 8096     5d/pop-to-ebp
 8097     c3/return
 8098 
 8099 test-get-with-wrong-offset-type:
 8100     # . prologue
 8101     55/push-ebp
 8102     89/<- %ebp 4/r32/esp
 8103     # setup
 8104     (clear-stream _test-input-stream)
 8105     (clear-stream $_test-input-buffered-file->buffer)
 8106     (clear-stream _test-output-stream)
 8107     (clear-stream $_test-output-buffered-file->buffer)
 8108     (clear-stream _test-error-stream)
 8109     (clear-stream $_test-error-buffered-file->buffer)
 8110     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8111     68/push 0/imm32
 8112     68/push 0/imm32
 8113     89/<- %edx 4/r32/esp
 8114     (tailor-exit-descriptor %edx 0x10)
 8115     #
 8116     (write _test-input-stream "fn foo {\n")
 8117     (write _test-input-stream "  var a: t\n")
 8118     (write _test-input-stream "  var b: int\n")
 8119     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 8120     (write _test-input-stream "}\n")
 8121     (write _test-input-stream "type t {\n")
 8122     (write _test-input-stream "  x: int\n")
 8123     (write _test-input-stream "}\n")
 8124     # convert
 8125     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8126     # registers except esp clobbered at this point
 8127     # restore ed
 8128     89/<- %edx 4/r32/esp
 8129     (flush _test-output-buffered-file)
 8130     (flush _test-error-buffered-file)
 8131 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8137     # check output
 8138     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 8139     (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")
 8140     # check that stop(1) was called
 8141     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 8142     # don't restore from ebp
 8143     81 0/subop/add %esp 8/imm32
 8144     # . epilogue
 8145     5d/pop-to-ebp
 8146     c3/return
 8147 
 8148 test-get-with-wrong-output-type:
 8149     # . prologue
 8150     55/push-ebp
 8151     89/<- %ebp 4/r32/esp
 8152     # setup
 8153     (clear-stream _test-input-stream)
 8154     (clear-stream $_test-input-buffered-file->buffer)
 8155     (clear-stream _test-output-stream)
 8156     (clear-stream $_test-output-buffered-file->buffer)
 8157     (clear-stream _test-error-stream)
 8158     (clear-stream $_test-error-buffered-file->buffer)
 8159     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8160     68/push 0/imm32
 8161     68/push 0/imm32
 8162     89/<- %edx 4/r32/esp
 8163     (tailor-exit-descriptor %edx 0x10)
 8164     #
 8165     (write _test-input-stream "fn foo {\n")
 8166     (write _test-input-stream "  var a: t\n")
 8167     (write _test-input-stream "  var c: (addr int)\n")
 8168     (write _test-input-stream "  c <- get a, x\n")
 8169     (write _test-input-stream "}\n")
 8170     (write _test-input-stream "type t {\n")
 8171     (write _test-input-stream "  x: int\n")
 8172     (write _test-input-stream "}\n")
 8173     # convert
 8174     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8175     # registers except esp clobbered at this point
 8176     # restore ed
 8177     89/<- %edx 4/r32/esp
 8178     (flush _test-output-buffered-file)
 8179     (flush _test-error-buffered-file)
 8180 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8186     # check output
 8187     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 8188     (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")
 8189     # check that stop(1) was called
 8190     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 8191     # don't restore from ebp
 8192     81 0/subop/add %esp 8/imm32
 8193     # . epilogue
 8194     5d/pop-to-ebp
 8195     c3/return
 8196 
 8197 test-get-with-wrong-output-type-2:
 8198     # . prologue
 8199     55/push-ebp
 8200     89/<- %ebp 4/r32/esp
 8201     # setup
 8202     (clear-stream _test-input-stream)
 8203     (clear-stream $_test-input-buffered-file->buffer)
 8204     (clear-stream _test-output-stream)
 8205     (clear-stream $_test-output-buffered-file->buffer)
 8206     (clear-stream _test-error-stream)
 8207     (clear-stream $_test-error-buffered-file->buffer)
 8208     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8209     68/push 0/imm32
 8210     68/push 0/imm32
 8211     89/<- %edx 4/r32/esp
 8212     (tailor-exit-descriptor %edx 0x10)
 8213     #
 8214     (write _test-input-stream "fn foo {\n")
 8215     (write _test-input-stream "  var a: t\n")
 8216     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 8217     (write _test-input-stream "}\n")
 8218     (write _test-input-stream "type t {\n")
 8219     (write _test-input-stream "  x: int\n")
 8220     (write _test-input-stream "}\n")
 8221     # convert
 8222     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8223     # registers except esp clobbered at this point
 8224     # restore ed
 8225     89/<- %edx 4/r32/esp
 8226     (flush _test-output-buffered-file)
 8227     (flush _test-error-buffered-file)
 8228 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8234     # check output
 8235     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 8236     (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")
 8237     # check that stop(1) was called
 8238     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 8239     # don't restore from ebp
 8240     81 0/subop/add %esp 8/imm32
 8241     # . epilogue
 8242     5d/pop-to-ebp
 8243     c3/return
 8244 
 8245 test-get-with-wrong-output-type-3:
 8246     # . prologue
 8247     55/push-ebp
 8248     89/<- %ebp 4/r32/esp
 8249     # setup
 8250     (clear-stream _test-input-stream)
 8251     (clear-stream $_test-input-buffered-file->buffer)
 8252     (clear-stream _test-output-stream)
 8253     (clear-stream $_test-output-buffered-file->buffer)
 8254     (clear-stream _test-error-stream)
 8255     (clear-stream $_test-error-buffered-file->buffer)
 8256     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8257     68/push 0/imm32
 8258     68/push 0/imm32
 8259     89/<- %edx 4/r32/esp
 8260     (tailor-exit-descriptor %edx 0x10)
 8261     #
 8262     (write _test-input-stream "fn foo {\n")
 8263     (write _test-input-stream "  var a: t\n")
 8264     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 8265     (write _test-input-stream "}\n")
 8266     (write _test-input-stream "type t {\n")
 8267     (write _test-input-stream "  x: int\n")
 8268     (write _test-input-stream "}\n")
 8269     # convert
 8270     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8271     # registers except esp clobbered at this point
 8272     # restore ed
 8273     89/<- %edx 4/r32/esp
 8274     (flush _test-output-buffered-file)
 8275     (flush _test-error-buffered-file)
 8276 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8282     # check output
 8283     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 8284     (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")
 8285     # check that stop(1) was called
 8286     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 8287     # don't restore from ebp
 8288     81 0/subop/add %esp 8/imm32
 8289     # . epilogue
 8290     5d/pop-to-ebp
 8291     c3/return
 8292 
 8293 test-get-with-wrong-output-type-4:
 8294     # . prologue
 8295     55/push-ebp
 8296     89/<- %ebp 4/r32/esp
 8297     # setup
 8298     (clear-stream _test-input-stream)
 8299     (clear-stream $_test-input-buffered-file->buffer)
 8300     (clear-stream _test-output-stream)
 8301     (clear-stream $_test-output-buffered-file->buffer)
 8302     (clear-stream _test-error-stream)
 8303     (clear-stream $_test-error-buffered-file->buffer)
 8304     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8305     68/push 0/imm32
 8306     68/push 0/imm32
 8307     89/<- %edx 4/r32/esp
 8308     (tailor-exit-descriptor %edx 0x10)
 8309     #
 8310     (write _test-input-stream "fn foo {\n")
 8311     (write _test-input-stream "  var a: t\n")
 8312     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 8313     (write _test-input-stream "}\n")
 8314     (write _test-input-stream "type t {\n")
 8315     (write _test-input-stream "  x: int\n")
 8316     (write _test-input-stream "}\n")
 8317     # convert
 8318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8319     # registers except esp clobbered at this point
 8320     # restore ed
 8321     89/<- %edx 4/r32/esp
 8322     (flush _test-output-buffered-file)
 8323     (flush _test-error-buffered-file)
 8324 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8330     # check output
 8331     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 8332     (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")
 8333     # check that stop(1) was called
 8334     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 8335     # don't restore from ebp
 8336     81 0/subop/add %esp 8/imm32
 8337     # . epilogue
 8338     5d/pop-to-ebp
 8339     c3/return
 8340 
 8341 test-get-with-wrong-output-type-5:
 8342     # . prologue
 8343     55/push-ebp
 8344     89/<- %ebp 4/r32/esp
 8345     # setup
 8346     (clear-stream _test-input-stream)
 8347     (clear-stream $_test-input-buffered-file->buffer)
 8348     (clear-stream _test-output-stream)
 8349     (clear-stream $_test-output-buffered-file->buffer)
 8350     #
 8351     (write _test-input-stream "fn foo {\n")
 8352     (write _test-input-stream "  var a: t\n")
 8353     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 8354     (write _test-input-stream "}\n")
 8355     (write _test-input-stream "type t {\n")
 8356     (write _test-input-stream "  x: (handle int)\n")
 8357     (write _test-input-stream "}\n")
 8358     # convert
 8359     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8360     (flush _test-output-buffered-file)
 8361     # no errors
 8362     # . epilogue
 8363     89/<- %esp 5/r32/ebp
 8364     5d/pop-to-ebp
 8365     c3/return
 8366 
 8367 test-get-with-too-few-inouts:
 8368     # . prologue
 8369     55/push-ebp
 8370     89/<- %ebp 4/r32/esp
 8371     # setup
 8372     (clear-stream _test-input-stream)
 8373     (clear-stream $_test-input-buffered-file->buffer)
 8374     (clear-stream _test-output-stream)
 8375     (clear-stream $_test-output-buffered-file->buffer)
 8376     (clear-stream _test-error-stream)
 8377     (clear-stream $_test-error-buffered-file->buffer)
 8378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8379     68/push 0/imm32
 8380     68/push 0/imm32
 8381     89/<- %edx 4/r32/esp
 8382     (tailor-exit-descriptor %edx 0x10)
 8383     #
 8384     (write _test-input-stream "fn foo {\n")
 8385     (write _test-input-stream "  var a: t\n")
 8386     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 8387     (write _test-input-stream "}\n")
 8388     (write _test-input-stream "type t {\n")
 8389     (write _test-input-stream "  x: int\n")
 8390     (write _test-input-stream "}\n")
 8391     # convert
 8392     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8393     # registers except esp clobbered at this point
 8394     # restore ed
 8395     89/<- %edx 4/r32/esp
 8396     (flush _test-output-buffered-file)
 8397     (flush _test-error-buffered-file)
 8398 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8404     # check output
 8405     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 8406     (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")
 8407     # check that stop(1) was called
 8408     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 8409     # don't restore from ebp
 8410     81 0/subop/add %esp 8/imm32
 8411     # . epilogue
 8412     5d/pop-to-ebp
 8413     c3/return
 8414 
 8415 test-get-with-too-many-inouts:
 8416     # . prologue
 8417     55/push-ebp
 8418     89/<- %ebp 4/r32/esp
 8419     # setup
 8420     (clear-stream _test-input-stream)
 8421     (clear-stream $_test-input-buffered-file->buffer)
 8422     (clear-stream _test-output-stream)
 8423     (clear-stream $_test-output-buffered-file->buffer)
 8424     (clear-stream _test-error-stream)
 8425     (clear-stream $_test-error-buffered-file->buffer)
 8426     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8427     68/push 0/imm32
 8428     68/push 0/imm32
 8429     89/<- %edx 4/r32/esp
 8430     (tailor-exit-descriptor %edx 0x10)
 8431     #
 8432     (write _test-input-stream "fn foo {\n")
 8433     (write _test-input-stream "  var a: t\n")
 8434     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 8435     (write _test-input-stream "}\n")
 8436     (write _test-input-stream "type t {\n")
 8437     (write _test-input-stream "  x: int\n")
 8438     (write _test-input-stream "}\n")
 8439     # convert
 8440     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8441     # registers except esp clobbered at this point
 8442     # restore ed
 8443     89/<- %edx 4/r32/esp
 8444     (flush _test-output-buffered-file)
 8445     (flush _test-error-buffered-file)
 8446 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8452     # check output
 8453     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 8454     (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")
 8455     # check that stop(1) was called
 8456     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 8457     # don't restore from ebp
 8458     81 0/subop/add %esp 8/imm32
 8459     # . epilogue
 8460     5d/pop-to-ebp
 8461     c3/return
 8462 
 8463 test-get-with-no-output:
 8464     # . prologue
 8465     55/push-ebp
 8466     89/<- %ebp 4/r32/esp
 8467     # setup
 8468     (clear-stream _test-input-stream)
 8469     (clear-stream $_test-input-buffered-file->buffer)
 8470     (clear-stream _test-output-stream)
 8471     (clear-stream $_test-output-buffered-file->buffer)
 8472     (clear-stream _test-error-stream)
 8473     (clear-stream $_test-error-buffered-file->buffer)
 8474     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8475     68/push 0/imm32
 8476     68/push 0/imm32
 8477     89/<- %edx 4/r32/esp
 8478     (tailor-exit-descriptor %edx 0x10)
 8479     #
 8480     (write _test-input-stream "fn foo {\n")
 8481     (write _test-input-stream "  var a: t\n")
 8482     (write _test-input-stream "  get a, x\n")
 8483     (write _test-input-stream "}\n")
 8484     (write _test-input-stream "type t {\n")
 8485     (write _test-input-stream "  x: int\n")
 8486     (write _test-input-stream "}\n")
 8487     # convert
 8488     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8489     # registers except esp clobbered at this point
 8490     # restore ed
 8491     89/<- %edx 4/r32/esp
 8492     (flush _test-output-buffered-file)
 8493     (flush _test-error-buffered-file)
 8494 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8500     # check output
 8501     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 8502     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 8503     # check that stop(1) was called
 8504     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 8505     # don't restore from ebp
 8506     81 0/subop/add %esp 8/imm32
 8507     # . epilogue
 8508     5d/pop-to-ebp
 8509     c3/return
 8510 
 8511 test-get-with-too-many-outputs:
 8512     # . prologue
 8513     55/push-ebp
 8514     89/<- %ebp 4/r32/esp
 8515     # setup
 8516     (clear-stream _test-input-stream)
 8517     (clear-stream $_test-input-buffered-file->buffer)
 8518     (clear-stream _test-output-stream)
 8519     (clear-stream $_test-output-buffered-file->buffer)
 8520     (clear-stream _test-error-stream)
 8521     (clear-stream $_test-error-buffered-file->buffer)
 8522     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8523     68/push 0/imm32
 8524     68/push 0/imm32
 8525     89/<- %edx 4/r32/esp
 8526     (tailor-exit-descriptor %edx 0x10)
 8527     #
 8528     (write _test-input-stream "fn foo {\n")
 8529     (write _test-input-stream "  var a: t\n")
 8530     (write _test-input-stream "  var b: int\n")
 8531     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 8532     (write _test-input-stream "  c, b <- get a, x\n")
 8533     (write _test-input-stream "}\n")
 8534     (write _test-input-stream "type t {\n")
 8535     (write _test-input-stream "  x: int\n")
 8536     (write _test-input-stream "}\n")
 8537     # convert
 8538     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8539     # registers except esp clobbered at this point
 8540     # restore ed
 8541     89/<- %edx 4/r32/esp
 8542     (flush _test-output-buffered-file)
 8543     (flush _test-error-buffered-file)
 8544 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8550     # check output
 8551     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 8552     (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")
 8553     # check that stop(1) was called
 8554     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 8555     # don't restore from ebp
 8556     81 0/subop/add %esp 8/imm32
 8557     # . epilogue
 8558     5d/pop-to-ebp
 8559     c3/return
 8560 
 8561 test-convert-array-of-user-defined-types:
 8562     # . prologue
 8563     55/push-ebp
 8564     89/<- %ebp 4/r32/esp
 8565     # setup
 8566     (clear-stream _test-input-stream)
 8567     (clear-stream $_test-input-buffered-file->buffer)
 8568     (clear-stream _test-output-stream)
 8569     (clear-stream $_test-output-buffered-file->buffer)
 8570     #
 8571     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 8572     (write _test-input-stream "  x: int\n")
 8573     (write _test-input-stream "  y: int\n")
 8574     (write _test-input-stream "}\n")
 8575     (write _test-input-stream "fn foo {\n")
 8576     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 8577     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 8578     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 8579     (write _test-input-stream "}\n")
 8580     # convert
 8581     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8582     (flush _test-output-buffered-file)
 8583 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8589     # check output
 8590     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 8591     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 8592     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 8593     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 8594     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 8595     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 8596     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 8597     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 8598     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 8599     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 8600     (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")
 8601     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/13")
 8602     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/14")
 8603     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/15")
 8604     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/16")
 8605     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/17")
 8606     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/18")
 8607     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/19")
 8608     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/20")
 8609     # . epilogue
 8610     89/<- %esp 5/r32/ebp
 8611     5d/pop-to-ebp
 8612     c3/return
 8613 
 8614 test-convert-length-of-array-of-user-defined-types-to-eax:
 8615     # . prologue
 8616     55/push-ebp
 8617     89/<- %ebp 4/r32/esp
 8618     # setup
 8619     (clear-stream _test-input-stream)
 8620     (clear-stream $_test-input-buffered-file->buffer)
 8621     (clear-stream _test-output-stream)
 8622     (clear-stream $_test-output-buffered-file->buffer)
 8623     #
 8624     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 8625     (write _test-input-stream "  x: int\n")
 8626     (write _test-input-stream "  y: int\n")
 8627     (write _test-input-stream "  z: int\n")
 8628     (write _test-input-stream "}\n")
 8629     (write _test-input-stream "fn foo {\n")
 8630     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 8631     (write _test-input-stream "  var x/eax: int <- length arr\n")
 8632     (write _test-input-stream "}\n")
 8633     # convert
 8634     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8635     (flush _test-output-buffered-file)
 8636 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8642     # check output
 8643     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 8644     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 8645     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 8646     (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")
 8647     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 8648     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 8649     # var arr
 8650     (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")
 8651     (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")
 8652     # length instruction
 8653     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 8654     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 8655     (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")
 8656     (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")
 8657     (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")
 8658     (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")
 8659     (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")
 8660     (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")
 8661     # reclaim arr
 8662     (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")
 8663     #
 8664     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 8665     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 8666     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 8667     (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")
 8668     (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")
 8669     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 8670     # . epilogue
 8671     89/<- %esp 5/r32/ebp
 8672     5d/pop-to-ebp
 8673     c3/return
 8674 
 8675 test-convert-length-of-array-of-user-defined-types-to-ecx:
 8676     # . prologue
 8677     55/push-ebp
 8678     89/<- %ebp 4/r32/esp
 8679     # setup
 8680     (clear-stream _test-input-stream)
 8681     (clear-stream $_test-input-buffered-file->buffer)
 8682     (clear-stream _test-output-stream)
 8683     (clear-stream $_test-output-buffered-file->buffer)
 8684     #
 8685     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 8686     (write _test-input-stream "  x: int\n")
 8687     (write _test-input-stream "  y: int\n")
 8688     (write _test-input-stream "  z: int\n")
 8689     (write _test-input-stream "}\n")
 8690     (write _test-input-stream "fn foo {\n")
 8691     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 8692     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 8693     (write _test-input-stream "}\n")
 8694     # convert
 8695     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8696     (flush _test-output-buffered-file)
 8697 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8703     # check output
 8704     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 8705     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 8706     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 8707     (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")
 8708     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 8709     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 8710     # var a
 8711     (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")
 8712     (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")
 8713     # var x
 8714     (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")
 8715     # length instruction
 8716     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 8717     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 8718     (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")
 8719     (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")
 8720     (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")
 8721     (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")
 8722     (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")
 8723     (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")
 8724     (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")
 8725     # reclaim x
 8726     (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")
 8727     # reclaim a
 8728     (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")
 8729     #
 8730     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 8731     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 8732     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 8733     (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")
 8734     (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")
 8735     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 8736     # . epilogue
 8737     89/<- %esp 5/r32/ebp
 8738     5d/pop-to-ebp
 8739     c3/return
 8740 
 8741 test-convert-length-of-array-of-user-defined-types-to-edx:
 8742     # . prologue
 8743     55/push-ebp
 8744     89/<- %ebp 4/r32/esp
 8745     # setup
 8746     (clear-stream _test-input-stream)
 8747     (clear-stream $_test-input-buffered-file->buffer)
 8748     (clear-stream _test-output-stream)
 8749     (clear-stream $_test-output-buffered-file->buffer)
 8750     #
 8751     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 8752     (write _test-input-stream "  x: int\n")
 8753     (write _test-input-stream "  y: int\n")
 8754     (write _test-input-stream "  z: int\n")
 8755     (write _test-input-stream "}\n")
 8756     (write _test-input-stream "fn foo {\n")
 8757     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 8758     (write _test-input-stream "  var x/edx: int <- length arr\n")
 8759     (write _test-input-stream "}\n")
 8760     # convert
 8761     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8762     (flush _test-output-buffered-file)
 8763 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8769     # check output
 8770     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 8771     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 8772     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 8773     (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")
 8774     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 8775     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 8776     # var a
 8777     (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")
 8778     (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")
 8779     # var x
 8780     (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")
 8781     # length instruction
 8782     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 8783     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 8784     (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")
 8785     (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")
 8786     (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")
 8787     (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")
 8788     (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")
 8789     (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")
 8790     (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")
 8791     # reclaim x
 8792     (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")
 8793     # reclaim a
 8794     (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")
 8795     #
 8796     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 8797     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 8798     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 8799     (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")
 8800     (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")
 8801     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 8802     # . epilogue
 8803     89/<- %esp 5/r32/ebp
 8804     5d/pop-to-ebp
 8805     c3/return
 8806 
 8807 test-convert-length-of-array-of-user-defined-types:
 8808     # . prologue
 8809     55/push-ebp
 8810     89/<- %ebp 4/r32/esp
 8811     # setup
 8812     (clear-stream _test-input-stream)
 8813     (clear-stream $_test-input-buffered-file->buffer)
 8814     (clear-stream _test-output-stream)
 8815     (clear-stream $_test-output-buffered-file->buffer)
 8816     #
 8817     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 8818     (write _test-input-stream "  x: int\n")
 8819     (write _test-input-stream "  y: int\n")
 8820     (write _test-input-stream "  z: int\n")
 8821     (write _test-input-stream "}\n")
 8822     (write _test-input-stream "fn foo {\n")
 8823     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 8824     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 8825     (write _test-input-stream "}\n")
 8826     # convert
 8827     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8828     (flush _test-output-buffered-file)
 8829 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8835     # check output
 8836     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 8837     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 8838     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 8839     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 8840     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 8841     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 8842     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 8843     (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")
 8844     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 8845     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 8846     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 8847     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 8848     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 8849     (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")
 8850     (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")
 8851     (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")
 8852     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 8853     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 8854     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 8855     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 8856     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 8857     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 8858     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 8859     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 8860     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 8861     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 8862     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 8863     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 8864     # . epilogue
 8865     89/<- %esp 5/r32/ebp
 8866     5d/pop-to-ebp
 8867     c3/return
 8868 
 8869 test-index-with-non-array-atom-base-type:
 8870     # . prologue
 8871     55/push-ebp
 8872     89/<- %ebp 4/r32/esp
 8873     # setup
 8874     (clear-stream _test-input-stream)
 8875     (clear-stream $_test-input-buffered-file->buffer)
 8876     (clear-stream _test-output-stream)
 8877     (clear-stream $_test-output-buffered-file->buffer)
 8878     (clear-stream _test-error-stream)
 8879     (clear-stream $_test-error-buffered-file->buffer)
 8880     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8881     68/push 0/imm32
 8882     68/push 0/imm32
 8883     89/<- %edx 4/r32/esp
 8884     (tailor-exit-descriptor %edx 0x10)
 8885     #
 8886     (write _test-input-stream "fn foo {\n")
 8887     (write _test-input-stream "  var a: int\n")
 8888     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 8889     (write _test-input-stream "}\n")
 8890     # convert
 8891     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8892     # registers except esp clobbered at this point
 8893     # restore ed
 8894     89/<- %edx 4/r32/esp
 8895     (flush _test-output-buffered-file)
 8896     (flush _test-error-buffered-file)
 8897 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8903     # check output
 8904     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 8905     (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")
 8906     # check that stop(1) was called
 8907     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 8908     # don't restore from ebp
 8909     81 0/subop/add %esp 8/imm32
 8910     # . epilogue
 8911     5d/pop-to-ebp
 8912     c3/return
 8913 
 8914 test-index-with-non-array-compound-base-type:
 8915     # . prologue
 8916     55/push-ebp
 8917     89/<- %ebp 4/r32/esp
 8918     # setup
 8919     (clear-stream _test-input-stream)
 8920     (clear-stream $_test-input-buffered-file->buffer)
 8921     (clear-stream _test-output-stream)
 8922     (clear-stream $_test-output-buffered-file->buffer)
 8923     (clear-stream _test-error-stream)
 8924     (clear-stream $_test-error-buffered-file->buffer)
 8925     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8926     68/push 0/imm32
 8927     68/push 0/imm32
 8928     89/<- %edx 4/r32/esp
 8929     (tailor-exit-descriptor %edx 0x10)
 8930     #
 8931     (write _test-input-stream "fn foo {\n")
 8932     (write _test-input-stream "  var a: (handle int)\n")
 8933     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 8934     (write _test-input-stream "}\n")
 8935     # convert
 8936     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8937     # registers except esp clobbered at this point
 8938     # restore ed
 8939     89/<- %edx 4/r32/esp
 8940     (flush _test-output-buffered-file)
 8941     (flush _test-error-buffered-file)
 8942 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8948     # check output
 8949     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 8950     (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")
 8951     # check that stop(1) was called
 8952     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 8953     # don't restore from ebp
 8954     81 0/subop/add %esp 8/imm32
 8955     # . epilogue
 8956     5d/pop-to-ebp
 8957     c3/return
 8958 
 8959 test-index-with-non-array-compound-base-type-2:
 8960     # . prologue
 8961     55/push-ebp
 8962     89/<- %ebp 4/r32/esp
 8963     # setup
 8964     (clear-stream _test-input-stream)
 8965     (clear-stream $_test-input-buffered-file->buffer)
 8966     (clear-stream _test-output-stream)
 8967     (clear-stream $_test-output-buffered-file->buffer)
 8968     (clear-stream _test-error-stream)
 8969     (clear-stream $_test-error-buffered-file->buffer)
 8970     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8971     68/push 0/imm32
 8972     68/push 0/imm32
 8973     89/<- %edx 4/r32/esp
 8974     (tailor-exit-descriptor %edx 0x10)
 8975     #
 8976     (write _test-input-stream "fn foo {\n")
 8977     (write _test-input-stream "  var a: (addr int)\n")
 8978     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 8979     (write _test-input-stream "}\n")
 8980     # convert
 8981     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8982     # registers except esp clobbered at this point
 8983     # restore ed
 8984     89/<- %edx 4/r32/esp
 8985     (flush _test-output-buffered-file)
 8986     (flush _test-error-buffered-file)
 8987 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8993     # check output
 8994     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 8995     (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")
 8996     # check that stop(1) was called
 8997     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 8998     # don't restore from ebp
 8999     81 0/subop/add %esp 8/imm32
 9000     # . epilogue
 9001     5d/pop-to-ebp
 9002     c3/return
 9003 
 9004 test-index-with-array-atom-base-type:
 9005     # . prologue
 9006     55/push-ebp
 9007     89/<- %ebp 4/r32/esp
 9008     # setup
 9009     (clear-stream _test-input-stream)
 9010     (clear-stream $_test-input-buffered-file->buffer)
 9011     (clear-stream _test-output-stream)
 9012     (clear-stream $_test-output-buffered-file->buffer)
 9013     (clear-stream _test-error-stream)
 9014     (clear-stream $_test-error-buffered-file->buffer)
 9015     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9016     68/push 0/imm32
 9017     68/push 0/imm32
 9018     89/<- %edx 4/r32/esp
 9019     (tailor-exit-descriptor %edx 0x10)
 9020     #
 9021     (write _test-input-stream "fn foo {\n")
 9022     (write _test-input-stream "  var a: array\n")
 9023     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9024     (write _test-input-stream "}\n")
 9025     # convert
 9026     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9027     # registers except esp clobbered at this point
 9028     # restore ed
 9029     89/<- %edx 4/r32/esp
 9030     (flush _test-output-buffered-file)
 9031     (flush _test-error-buffered-file)
 9032 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9038     # check output
 9039     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 9040     (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")
 9041     # check that stop(1) was called
 9042     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 9043     # don't restore from ebp
 9044     81 0/subop/add %esp 8/imm32
 9045     # . epilogue
 9046     5d/pop-to-ebp
 9047     c3/return
 9048 
 9049 test-index-with-addr-base-on-stack:
 9050     # . prologue
 9051     55/push-ebp
 9052     89/<- %ebp 4/r32/esp
 9053     # setup
 9054     (clear-stream _test-input-stream)
 9055     (clear-stream $_test-input-buffered-file->buffer)
 9056     (clear-stream _test-output-stream)
 9057     (clear-stream $_test-output-buffered-file->buffer)
 9058     (clear-stream _test-error-stream)
 9059     (clear-stream $_test-error-buffered-file->buffer)
 9060     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9061     68/push 0/imm32
 9062     68/push 0/imm32
 9063     89/<- %edx 4/r32/esp
 9064     (tailor-exit-descriptor %edx 0x10)
 9065     #
 9066     (write _test-input-stream "fn foo {\n")
 9067     (write _test-input-stream "  var a: (addr array int)\n")
 9068     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9069     (write _test-input-stream "}\n")
 9070     # convert
 9071     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9072     # registers except esp clobbered at this point
 9073     # restore ed
 9074     89/<- %edx 4/r32/esp
 9075     (flush _test-output-buffered-file)
 9076     (flush _test-error-buffered-file)
 9077 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9083     # check output
 9084     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
 9085     (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")
 9086     # check that stop(1) was called
 9087     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
 9088     # don't restore from ebp
 9089     81 0/subop/add %esp 8/imm32
 9090     # . epilogue
 9091     5d/pop-to-ebp
 9092     c3/return
 9093 
 9094 test-index-with-wrong-index-type:
 9095     # . prologue
 9096     55/push-ebp
 9097     89/<- %ebp 4/r32/esp
 9098     # setup
 9099     (clear-stream _test-input-stream)
 9100     (clear-stream $_test-input-buffered-file->buffer)
 9101     (clear-stream _test-output-stream)
 9102     (clear-stream $_test-output-buffered-file->buffer)
 9103     (clear-stream _test-error-stream)
 9104     (clear-stream $_test-error-buffered-file->buffer)
 9105     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9106     68/push 0/imm32
 9107     68/push 0/imm32
 9108     89/<- %edx 4/r32/esp
 9109     (tailor-exit-descriptor %edx 0x10)
 9110     #
 9111     (write _test-input-stream "fn foo {\n")
 9112     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9113     (write _test-input-stream "  var b: boolean\n")
 9114     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9115     (write _test-input-stream "}\n")
 9116     # convert
 9117     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9118     # registers except esp clobbered at this point
 9119     # restore ed
 9120     89/<- %edx 4/r32/esp
 9121     (flush _test-output-buffered-file)
 9122     (flush _test-error-buffered-file)
 9123 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9129     # check output
 9130     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
 9131     (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")
 9132     # check that stop(1) was called
 9133     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
 9134     # don't restore from ebp
 9135     81 0/subop/add %esp 8/imm32
 9136     # . epilogue
 9137     5d/pop-to-ebp
 9138     c3/return
 9139 
 9140 test-index-with-offset-atom-index-type:
 9141     # . prologue
 9142     55/push-ebp
 9143     89/<- %ebp 4/r32/esp
 9144     # setup
 9145     (clear-stream _test-input-stream)
 9146     (clear-stream $_test-input-buffered-file->buffer)
 9147     (clear-stream _test-output-stream)
 9148     (clear-stream $_test-output-buffered-file->buffer)
 9149     (clear-stream _test-error-stream)
 9150     (clear-stream $_test-error-buffered-file->buffer)
 9151     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9152     68/push 0/imm32
 9153     68/push 0/imm32
 9154     89/<- %edx 4/r32/esp
 9155     (tailor-exit-descriptor %edx 0x10)
 9156     #
 9157     (write _test-input-stream "fn foo {\n")
 9158     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9159     (write _test-input-stream "  var b: offset\n")
 9160     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9161     (write _test-input-stream "}\n")
 9162     # convert
 9163     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9164     # registers except esp clobbered at this point
 9165     # restore ed
 9166     89/<- %edx 4/r32/esp
 9167     (flush _test-output-buffered-file)
 9168     (flush _test-error-buffered-file)
 9169 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9175     # check output
 9176     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
 9177     (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")
 9178     # check that stop(1) was called
 9179     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
 9180     # don't restore from ebp
 9181     81 0/subop/add %esp 8/imm32
 9182     # . epilogue
 9183     5d/pop-to-ebp
 9184     c3/return
 9185 
 9186 test-index-with-offset-on-stack:
 9187     # . prologue
 9188     55/push-ebp
 9189     89/<- %ebp 4/r32/esp
 9190     # setup
 9191     (clear-stream _test-input-stream)
 9192     (clear-stream $_test-input-buffered-file->buffer)
 9193     (clear-stream _test-output-stream)
 9194     (clear-stream $_test-output-buffered-file->buffer)
 9195     (clear-stream _test-error-stream)
 9196     (clear-stream $_test-error-buffered-file->buffer)
 9197     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9198     68/push 0/imm32
 9199     68/push 0/imm32
 9200     89/<- %edx 4/r32/esp
 9201     (tailor-exit-descriptor %edx 0x10)
 9202     #
 9203     (write _test-input-stream "fn foo {\n")
 9204     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9205     (write _test-input-stream "  var b: int\n")
 9206     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9207     (write _test-input-stream "}\n")
 9208     # convert
 9209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9210     # registers except esp clobbered at this point
 9211     # restore ed
 9212     89/<- %edx 4/r32/esp
 9213     (flush _test-output-buffered-file)
 9214     (flush _test-error-buffered-file)
 9215 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9221     # check output
 9222     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
 9223     (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")
 9224     # check that stop(1) was called
 9225     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
 9226     # don't restore from ebp
 9227     81 0/subop/add %esp 8/imm32
 9228     # . epilogue
 9229     5d/pop-to-ebp
 9230     c3/return
 9231 
 9232 test-index-needs-offset-type:
 9233     # . prologue
 9234     55/push-ebp
 9235     89/<- %ebp 4/r32/esp
 9236     # setup
 9237     (clear-stream _test-input-stream)
 9238     (clear-stream $_test-input-buffered-file->buffer)
 9239     (clear-stream _test-output-stream)
 9240     (clear-stream $_test-output-buffered-file->buffer)
 9241     (clear-stream _test-error-stream)
 9242     (clear-stream $_test-error-buffered-file->buffer)
 9243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9244     68/push 0/imm32
 9245     68/push 0/imm32
 9246     89/<- %edx 4/r32/esp
 9247     (tailor-exit-descriptor %edx 0x10)
 9248     #
 9249     (write _test-input-stream "fn foo {\n")
 9250     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
 9251     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 9252     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9253     (write _test-input-stream "}\n")
 9254     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
 9255     (write _test-input-stream "  x: int\n")
 9256     (write _test-input-stream "  y: int\n")
 9257     (write _test-input-stream "  z: int\n")
 9258     (write _test-input-stream "}\n")
 9259     # convert
 9260     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9261     # registers except esp clobbered at this point
 9262     # restore ed
 9263     89/<- %edx 4/r32/esp
 9264     (flush _test-output-buffered-file)
 9265     (flush _test-error-buffered-file)
 9266 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9272     # check output
 9273     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
 9274     (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")
 9275     # check that stop(1) was called
 9276     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
 9277     # don't restore from ebp
 9278     81 0/subop/add %esp 8/imm32
 9279     # . epilogue
 9280     5d/pop-to-ebp
 9281     c3/return
 9282 
 9283 test-index-with-output-not-address:
 9284     # . prologue
 9285     55/push-ebp
 9286     89/<- %ebp 4/r32/esp
 9287     # setup
 9288     (clear-stream _test-input-stream)
 9289     (clear-stream $_test-input-buffered-file->buffer)
 9290     (clear-stream _test-output-stream)
 9291     (clear-stream $_test-output-buffered-file->buffer)
 9292     (clear-stream _test-error-stream)
 9293     (clear-stream $_test-error-buffered-file->buffer)
 9294     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9295     68/push 0/imm32
 9296     68/push 0/imm32
 9297     89/<- %edx 4/r32/esp
 9298     (tailor-exit-descriptor %edx 0x10)
 9299     #
 9300     (write _test-input-stream "fn foo {\n")
 9301     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9302     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
 9303     (write _test-input-stream "}\n")
 9304     # convert
 9305     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9306     # registers except esp clobbered at this point
 9307     # restore ed
 9308     89/<- %edx 4/r32/esp
 9309     (flush _test-output-buffered-file)
 9310     (flush _test-error-buffered-file)
 9311 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9317     # check output
 9318     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
 9319     (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")
 9320     # check that stop(1) was called
 9321     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
 9322     # don't restore from ebp
 9323     81 0/subop/add %esp 8/imm32
 9324     # . epilogue
 9325     5d/pop-to-ebp
 9326     c3/return
 9327 
 9328 test-index-with-output-not-address-2:
 9329     # . prologue
 9330     55/push-ebp
 9331     89/<- %ebp 4/r32/esp
 9332     # setup
 9333     (clear-stream _test-input-stream)
 9334     (clear-stream $_test-input-buffered-file->buffer)
 9335     (clear-stream _test-output-stream)
 9336     (clear-stream $_test-output-buffered-file->buffer)
 9337     (clear-stream _test-error-stream)
 9338     (clear-stream $_test-error-buffered-file->buffer)
 9339     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9340     68/push 0/imm32
 9341     68/push 0/imm32
 9342     89/<- %edx 4/r32/esp
 9343     (tailor-exit-descriptor %edx 0x10)
 9344     #
 9345     (write _test-input-stream "fn foo {\n")
 9346     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9347     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
 9348     (write _test-input-stream "}\n")
 9349     # convert
 9350     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9351     # registers except esp clobbered at this point
 9352     # restore ed
 9353     89/<- %edx 4/r32/esp
 9354     (flush _test-output-buffered-file)
 9355     (flush _test-error-buffered-file)
 9356 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9362     # check output
 9363     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
 9364     (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")
 9365     # check that stop(1) was called
 9366     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
 9367     # don't restore from ebp
 9368     81 0/subop/add %esp 8/imm32
 9369     # . epilogue
 9370     5d/pop-to-ebp
 9371     c3/return
 9372 
 9373 test-index-with-wrong-output-type:
 9374     # . prologue
 9375     55/push-ebp
 9376     89/<- %ebp 4/r32/esp
 9377     # setup
 9378     (clear-stream _test-input-stream)
 9379     (clear-stream $_test-input-buffered-file->buffer)
 9380     (clear-stream _test-output-stream)
 9381     (clear-stream $_test-output-buffered-file->buffer)
 9382     (clear-stream _test-error-stream)
 9383     (clear-stream $_test-error-buffered-file->buffer)
 9384     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9385     68/push 0/imm32
 9386     68/push 0/imm32
 9387     89/<- %edx 4/r32/esp
 9388     (tailor-exit-descriptor %edx 0x10)
 9389     #
 9390     (write _test-input-stream "fn foo {\n")
 9391     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9392     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
 9393     (write _test-input-stream "}\n")
 9394     # convert
 9395     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9396     # registers except esp clobbered at this point
 9397     # restore ed
 9398     89/<- %edx 4/r32/esp
 9399     (flush _test-output-buffered-file)
 9400     (flush _test-error-buffered-file)
 9401 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9407     # check output
 9408     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
 9409     (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")
 9410     # check that stop(1) was called
 9411     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
 9412     # don't restore from ebp
 9413     81 0/subop/add %esp 8/imm32
 9414     # . epilogue
 9415     5d/pop-to-ebp
 9416     c3/return
 9417 
 9418 test-index-with-wrong-output-compound-type:
 9419     # . prologue
 9420     55/push-ebp
 9421     89/<- %ebp 4/r32/esp
 9422     # setup
 9423     (clear-stream _test-input-stream)
 9424     (clear-stream $_test-input-buffered-file->buffer)
 9425     (clear-stream _test-output-stream)
 9426     (clear-stream $_test-output-buffered-file->buffer)
 9427     (clear-stream _test-error-stream)
 9428     (clear-stream $_test-error-buffered-file->buffer)
 9429     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9430     68/push 0/imm32
 9431     68/push 0/imm32
 9432     89/<- %edx 4/r32/esp
 9433     (tailor-exit-descriptor %edx 0x10)
 9434     #
 9435     (write _test-input-stream "fn foo {\n")
 9436     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 9437     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
 9438     (write _test-input-stream "}\n")
 9439     # convert
 9440     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9441     # registers except esp clobbered at this point
 9442     # restore ed
 9443     89/<- %edx 4/r32/esp
 9444     (flush _test-output-buffered-file)
 9445     (flush _test-error-buffered-file)
 9446 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9452     # check output
 9453     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
 9454     (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")
 9455     # check that stop(1) was called
 9456     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
 9457     # don't restore from ebp
 9458     81 0/subop/add %esp 8/imm32
 9459     # . epilogue
 9460     5d/pop-to-ebp
 9461     c3/return
 9462 
 9463 test-index-with-no-inouts:
 9464     # . prologue
 9465     55/push-ebp
 9466     89/<- %ebp 4/r32/esp
 9467     # setup
 9468     (clear-stream _test-input-stream)
 9469     (clear-stream $_test-input-buffered-file->buffer)
 9470     (clear-stream _test-output-stream)
 9471     (clear-stream $_test-output-buffered-file->buffer)
 9472     (clear-stream _test-error-stream)
 9473     (clear-stream $_test-error-buffered-file->buffer)
 9474     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9475     68/push 0/imm32
 9476     68/push 0/imm32
 9477     89/<- %edx 4/r32/esp
 9478     (tailor-exit-descriptor %edx 0x10)
 9479     #
 9480     (write _test-input-stream "fn foo {\n")
 9481     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
 9482     (write _test-input-stream "}\n")
 9483     # convert
 9484     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9485     # registers except esp clobbered at this point
 9486     # restore ed
 9487     89/<- %edx 4/r32/esp
 9488     (flush _test-output-buffered-file)
 9489     (flush _test-error-buffered-file)
 9490 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9496     # check output
 9497     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
 9498     (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")
 9499     # check that stop(1) was called
 9500     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
 9501     # don't restore from ebp
 9502     81 0/subop/add %esp 8/imm32
 9503     # . epilogue
 9504     5d/pop-to-ebp
 9505     c3/return
 9506 
 9507 test-index-with-too-few-inouts:
 9508     # . prologue
 9509     55/push-ebp
 9510     89/<- %ebp 4/r32/esp
 9511     # setup
 9512     (clear-stream _test-input-stream)
 9513     (clear-stream $_test-input-buffered-file->buffer)
 9514     (clear-stream _test-output-stream)
 9515     (clear-stream $_test-output-buffered-file->buffer)
 9516     (clear-stream _test-error-stream)
 9517     (clear-stream $_test-error-buffered-file->buffer)
 9518     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9519     68/push 0/imm32
 9520     68/push 0/imm32
 9521     89/<- %edx 4/r32/esp
 9522     (tailor-exit-descriptor %edx 0x10)
 9523     #
 9524     (write _test-input-stream "fn foo {\n")
 9525     (write _test-input-stream "  var a: (array int 3)\n")
 9526     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
 9527     (write _test-input-stream "}\n")
 9528     # convert
 9529     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9530     # registers except esp clobbered at this point
 9531     # restore ed
 9532     89/<- %edx 4/r32/esp
 9533     (flush _test-output-buffered-file)
 9534     (flush _test-error-buffered-file)
 9535 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9541     # check output
 9542     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
 9543     (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")
 9544     # check that stop(1) was called
 9545     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
 9546     # don't restore from ebp
 9547     81 0/subop/add %esp 8/imm32
 9548     # . epilogue
 9549     5d/pop-to-ebp
 9550     c3/return
 9551 
 9552 test-index-with-too-many-inouts:
 9553     # . prologue
 9554     55/push-ebp
 9555     89/<- %ebp 4/r32/esp
 9556     # setup
 9557     (clear-stream _test-input-stream)
 9558     (clear-stream $_test-input-buffered-file->buffer)
 9559     (clear-stream _test-output-stream)
 9560     (clear-stream $_test-output-buffered-file->buffer)
 9561     (clear-stream _test-error-stream)
 9562     (clear-stream $_test-error-buffered-file->buffer)
 9563     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9564     68/push 0/imm32
 9565     68/push 0/imm32
 9566     89/<- %edx 4/r32/esp
 9567     (tailor-exit-descriptor %edx 0x10)
 9568     #
 9569     (write _test-input-stream "fn foo {\n")
 9570     (write _test-input-stream "  var a: (array int 3)\n")
 9571     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
 9572     (write _test-input-stream "}\n")
 9573     # convert
 9574     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9575     # registers except esp clobbered at this point
 9576     # restore ed
 9577     89/<- %edx 4/r32/esp
 9578     (flush _test-output-buffered-file)
 9579     (flush _test-error-buffered-file)
 9580 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9586     # check output
 9587     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
 9588     (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")
 9589     # check that stop(1) was called
 9590     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
 9591     # don't restore from ebp
 9592     81 0/subop/add %esp 8/imm32
 9593     # . epilogue
 9594     5d/pop-to-ebp
 9595     c3/return
 9596 
 9597 test-index-with-no-output:
 9598     # . prologue
 9599     55/push-ebp
 9600     89/<- %ebp 4/r32/esp
 9601     # setup
 9602     (clear-stream _test-input-stream)
 9603     (clear-stream $_test-input-buffered-file->buffer)
 9604     (clear-stream _test-output-stream)
 9605     (clear-stream $_test-output-buffered-file->buffer)
 9606     (clear-stream _test-error-stream)
 9607     (clear-stream $_test-error-buffered-file->buffer)
 9608     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9609     68/push 0/imm32
 9610     68/push 0/imm32
 9611     89/<- %edx 4/r32/esp
 9612     (tailor-exit-descriptor %edx 0x10)
 9613     #
 9614     (write _test-input-stream "fn foo {\n")
 9615     (write _test-input-stream "  var a: (array int 3)\n")
 9616     (write _test-input-stream "  index a, 0\n")
 9617     (write _test-input-stream "}\n")
 9618     # convert
 9619     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9620     # registers except esp clobbered at this point
 9621     # restore ed
 9622     89/<- %edx 4/r32/esp
 9623     (flush _test-output-buffered-file)
 9624     (flush _test-error-buffered-file)
 9625 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9631     # check output
 9632     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
 9633     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
 9634     # check that stop(1) was called
 9635     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
 9636     # don't restore from ebp
 9637     81 0/subop/add %esp 8/imm32
 9638     # . epilogue
 9639     5d/pop-to-ebp
 9640     c3/return
 9641 
 9642 test-index-with-too-many-outputs:
 9643     # . prologue
 9644     55/push-ebp
 9645     89/<- %ebp 4/r32/esp
 9646     # setup
 9647     (clear-stream _test-input-stream)
 9648     (clear-stream $_test-input-buffered-file->buffer)
 9649     (clear-stream _test-output-stream)
 9650     (clear-stream $_test-output-buffered-file->buffer)
 9651     (clear-stream _test-error-stream)
 9652     (clear-stream $_test-error-buffered-file->buffer)
 9653     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9654     68/push 0/imm32
 9655     68/push 0/imm32
 9656     89/<- %edx 4/r32/esp
 9657     (tailor-exit-descriptor %edx 0x10)
 9658     #
 9659     (write _test-input-stream "fn foo {\n")
 9660     (write _test-input-stream "  var a: (array int 3)\n")
 9661     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 9662     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
 9663     (write _test-input-stream "  b, c <- index a, 0\n")
 9664     (write _test-input-stream "}\n")
 9665     # convert
 9666     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9667     # registers except esp clobbered at this point
 9668     # restore ed
 9669     89/<- %edx 4/r32/esp
 9670     (flush _test-output-buffered-file)
 9671     (flush _test-error-buffered-file)
 9672 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9678     # check output
 9679     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
 9680     (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")
 9681     # check that stop(1) was called
 9682     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
 9683     # don't restore from ebp
 9684     81 0/subop/add %esp 8/imm32
 9685     # . epilogue
 9686     5d/pop-to-ebp
 9687     c3/return
 9688 
 9689 test-compute-offset-with-non-array-atom-base-type:
 9690     # . prologue
 9691     55/push-ebp
 9692     89/<- %ebp 4/r32/esp
 9693     # setup
 9694     (clear-stream _test-input-stream)
 9695     (clear-stream $_test-input-buffered-file->buffer)
 9696     (clear-stream _test-output-stream)
 9697     (clear-stream $_test-output-buffered-file->buffer)
 9698     (clear-stream _test-error-stream)
 9699     (clear-stream $_test-error-buffered-file->buffer)
 9700     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9701     68/push 0/imm32
 9702     68/push 0/imm32
 9703     89/<- %edx 4/r32/esp
 9704     (tailor-exit-descriptor %edx 0x10)
 9705     #
 9706     (write _test-input-stream "fn foo {\n")
 9707     (write _test-input-stream "  var a: int\n")
 9708     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 9709     (write _test-input-stream "}\n")
 9710     # convert
 9711     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9712     # registers except esp clobbered at this point
 9713     # restore ed
 9714     89/<- %edx 4/r32/esp
 9715     (flush _test-output-buffered-file)
 9716     (flush _test-error-buffered-file)
 9717 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9723     # check output
 9724     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
 9725     (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")
 9726     # check that stop(1) was called
 9727     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
 9728     # don't restore from ebp
 9729     81 0/subop/add %esp 8/imm32
 9730     # . epilogue
 9731     5d/pop-to-ebp
 9732     c3/return
 9733 
 9734 test-compute-offset-with-non-array-compound-base-type:
 9735     # . prologue
 9736     55/push-ebp
 9737     89/<- %ebp 4/r32/esp
 9738     # setup
 9739     (clear-stream _test-input-stream)
 9740     (clear-stream $_test-input-buffered-file->buffer)
 9741     (clear-stream _test-output-stream)
 9742     (clear-stream $_test-output-buffered-file->buffer)
 9743     (clear-stream _test-error-stream)
 9744     (clear-stream $_test-error-buffered-file->buffer)
 9745     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9746     68/push 0/imm32
 9747     68/push 0/imm32
 9748     89/<- %edx 4/r32/esp
 9749     (tailor-exit-descriptor %edx 0x10)
 9750     #
 9751     (write _test-input-stream "fn foo {\n")
 9752     (write _test-input-stream "  var a: (handle int)\n")
 9753     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 9754     (write _test-input-stream "}\n")
 9755     # convert
 9756     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9757     # registers except esp clobbered at this point
 9758     # restore ed
 9759     89/<- %edx 4/r32/esp
 9760     (flush _test-output-buffered-file)
 9761     (flush _test-error-buffered-file)
 9762 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9768     # check output
 9769     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
 9770     (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")
 9771     # check that stop(1) was called
 9772     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
 9773     # don't restore from ebp
 9774     81 0/subop/add %esp 8/imm32
 9775     # . epilogue
 9776     5d/pop-to-ebp
 9777     c3/return
 9778 
 9779 test-compute-offset-with-non-array-compound-base-type-2:
 9780     # . prologue
 9781     55/push-ebp
 9782     89/<- %ebp 4/r32/esp
 9783     # setup
 9784     (clear-stream _test-input-stream)
 9785     (clear-stream $_test-input-buffered-file->buffer)
 9786     (clear-stream _test-output-stream)
 9787     (clear-stream $_test-output-buffered-file->buffer)
 9788     (clear-stream _test-error-stream)
 9789     (clear-stream $_test-error-buffered-file->buffer)
 9790     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9791     68/push 0/imm32
 9792     68/push 0/imm32
 9793     89/<- %edx 4/r32/esp
 9794     (tailor-exit-descriptor %edx 0x10)
 9795     #
 9796     (write _test-input-stream "fn foo {\n")
 9797     (write _test-input-stream "  var a: (addr int)\n")
 9798     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 9799     (write _test-input-stream "}\n")
 9800     # convert
 9801     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9802     # registers except esp clobbered at this point
 9803     # restore ed
 9804     89/<- %edx 4/r32/esp
 9805     (flush _test-output-buffered-file)
 9806     (flush _test-error-buffered-file)
 9807 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9813     # check output
 9814     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
 9815     (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")
 9816     # check that stop(1) was called
 9817     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
 9818     # don't restore from ebp
 9819     81 0/subop/add %esp 8/imm32
 9820     # . epilogue
 9821     5d/pop-to-ebp
 9822     c3/return
 9823 
 9824 test-compute-offset-with-array-atom-base-type:
 9825     # . prologue
 9826     55/push-ebp
 9827     89/<- %ebp 4/r32/esp
 9828     # setup
 9829     (clear-stream _test-input-stream)
 9830     (clear-stream $_test-input-buffered-file->buffer)
 9831     (clear-stream _test-output-stream)
 9832     (clear-stream $_test-output-buffered-file->buffer)
 9833     (clear-stream _test-error-stream)
 9834     (clear-stream $_test-error-buffered-file->buffer)
 9835     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9836     68/push 0/imm32
 9837     68/push 0/imm32
 9838     89/<- %edx 4/r32/esp
 9839     (tailor-exit-descriptor %edx 0x10)
 9840     #
 9841     (write _test-input-stream "fn foo {\n")
 9842     (write _test-input-stream "  var a: array\n")
 9843     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 9844     (write _test-input-stream "}\n")
 9845     # convert
 9846     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9847     # registers except esp clobbered at this point
 9848     # restore ed
 9849     89/<- %edx 4/r32/esp
 9850     (flush _test-output-buffered-file)
 9851     (flush _test-error-buffered-file)
 9852 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9858     # check output
 9859     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
 9860     (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")
 9861     # check that stop(1) was called
 9862     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
 9863     # don't restore from ebp
 9864     81 0/subop/add %esp 8/imm32
 9865     # . epilogue
 9866     5d/pop-to-ebp
 9867     c3/return
 9868 
 9869 test-compute-offset-with-wrong-index-type:
 9870     # . prologue
 9871     55/push-ebp
 9872     89/<- %ebp 4/r32/esp
 9873     # setup
 9874     (clear-stream _test-input-stream)
 9875     (clear-stream $_test-input-buffered-file->buffer)
 9876     (clear-stream _test-output-stream)
 9877     (clear-stream $_test-output-buffered-file->buffer)
 9878     (clear-stream _test-error-stream)
 9879     (clear-stream $_test-error-buffered-file->buffer)
 9880     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9881     68/push 0/imm32
 9882     68/push 0/imm32
 9883     89/<- %edx 4/r32/esp
 9884     (tailor-exit-descriptor %edx 0x10)
 9885     #
 9886     (write _test-input-stream "fn foo {\n")
 9887     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9888     (write _test-input-stream "  var b: boolean\n")
 9889     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
 9890     (write _test-input-stream "}\n")
 9891     # convert
 9892     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9893     # registers except esp clobbered at this point
 9894     # restore ed
 9895     89/<- %edx 4/r32/esp
 9896     (flush _test-output-buffered-file)
 9897     (flush _test-error-buffered-file)
 9898 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9904     # check output
 9905     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
 9906     (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")
 9907     # check that stop(1) was called
 9908     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
 9909     # don't restore from ebp
 9910     81 0/subop/add %esp 8/imm32
 9911     # . epilogue
 9912     5d/pop-to-ebp
 9913     c3/return
 9914 
 9915 test-compute-offset-with-output-not-offset:
 9916     # . prologue
 9917     55/push-ebp
 9918     89/<- %ebp 4/r32/esp
 9919     # setup
 9920     (clear-stream _test-input-stream)
 9921     (clear-stream $_test-input-buffered-file->buffer)
 9922     (clear-stream _test-output-stream)
 9923     (clear-stream $_test-output-buffered-file->buffer)
 9924     (clear-stream _test-error-stream)
 9925     (clear-stream $_test-error-buffered-file->buffer)
 9926     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9927     68/push 0/imm32
 9928     68/push 0/imm32
 9929     89/<- %edx 4/r32/esp
 9930     (tailor-exit-descriptor %edx 0x10)
 9931     #
 9932     (write _test-input-stream "fn foo {\n")
 9933     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9934     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
 9935     (write _test-input-stream "}\n")
 9936     # convert
 9937     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9938     # registers except esp clobbered at this point
 9939     # restore ed
 9940     89/<- %edx 4/r32/esp
 9941     (flush _test-output-buffered-file)
 9942     (flush _test-error-buffered-file)
 9943 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9949     # check output
 9950     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
 9951     (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")
 9952     # check that stop(1) was called
 9953     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
 9954     # don't restore from ebp
 9955     81 0/subop/add %esp 8/imm32
 9956     # . epilogue
 9957     5d/pop-to-ebp
 9958     c3/return
 9959 
 9960 test-compute-offset-with-output-not-address-2:
 9961     # . prologue
 9962     55/push-ebp
 9963     89/<- %ebp 4/r32/esp
 9964     # setup
 9965     (clear-stream _test-input-stream)
 9966     (clear-stream $_test-input-buffered-file->buffer)
 9967     (clear-stream _test-output-stream)
 9968     (clear-stream $_test-output-buffered-file->buffer)
 9969     (clear-stream _test-error-stream)
 9970     (clear-stream $_test-error-buffered-file->buffer)
 9971     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9972     68/push 0/imm32
 9973     68/push 0/imm32
 9974     89/<- %edx 4/r32/esp
 9975     (tailor-exit-descriptor %edx 0x10)
 9976     #
 9977     (write _test-input-stream "fn foo {\n")
 9978     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9979     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
 9980     (write _test-input-stream "}\n")
 9981     # convert
 9982     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9983     # registers except esp clobbered at this point
 9984     # restore ed
 9985     89/<- %edx 4/r32/esp
 9986     (flush _test-output-buffered-file)
 9987     (flush _test-error-buffered-file)
 9988 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9994     # check output
 9995     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
 9996     (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")
 9997     # check that stop(1) was called
 9998     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
 9999     # don't restore from ebp
10000     81 0/subop/add %esp 8/imm32
10001     # . epilogue
10002     5d/pop-to-ebp
10003     c3/return
10004 
10005 test-compute-offset-with-wrong-output-type:
10006     # . prologue
10007     55/push-ebp
10008     89/<- %ebp 4/r32/esp
10009     # setup
10010     (clear-stream _test-input-stream)
10011     (clear-stream $_test-input-buffered-file->buffer)
10012     (clear-stream _test-output-stream)
10013     (clear-stream $_test-output-buffered-file->buffer)
10014     (clear-stream _test-error-stream)
10015     (clear-stream $_test-error-buffered-file->buffer)
10016     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10017     68/push 0/imm32
10018     68/push 0/imm32
10019     89/<- %edx 4/r32/esp
10020     (tailor-exit-descriptor %edx 0x10)
10021     #
10022     (write _test-input-stream "fn foo {\n")
10023     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10024     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
10025     (write _test-input-stream "}\n")
10026     # convert
10027     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10028     # registers except esp clobbered at this point
10029     # restore ed
10030     89/<- %edx 4/r32/esp
10031     (flush _test-output-buffered-file)
10032     (flush _test-error-buffered-file)
10033 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10039     # check output
10040     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
10041     (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")
10042     # check that stop(1) was called
10043     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
10044     # don't restore from ebp
10045     81 0/subop/add %esp 8/imm32
10046     # . epilogue
10047     5d/pop-to-ebp
10048     c3/return
10049 
10050 test-compute-offset-with-wrong-output-compound-type:
10051     # . prologue
10052     55/push-ebp
10053     89/<- %ebp 4/r32/esp
10054     # setup
10055     (clear-stream _test-input-stream)
10056     (clear-stream $_test-input-buffered-file->buffer)
10057     (clear-stream _test-output-stream)
10058     (clear-stream $_test-output-buffered-file->buffer)
10059     (clear-stream _test-error-stream)
10060     (clear-stream $_test-error-buffered-file->buffer)
10061     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10062     68/push 0/imm32
10063     68/push 0/imm32
10064     89/<- %edx 4/r32/esp
10065     (tailor-exit-descriptor %edx 0x10)
10066     #
10067     (write _test-input-stream "fn foo {\n")
10068     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
10069     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
10070     (write _test-input-stream "}\n")
10071     # convert
10072     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10073     # registers except esp clobbered at this point
10074     # restore ed
10075     89/<- %edx 4/r32/esp
10076     (flush _test-output-buffered-file)
10077     (flush _test-error-buffered-file)
10078 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10084     # check output
10085     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
10086     (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")
10087     # check that stop(1) was called
10088     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
10089     # don't restore from ebp
10090     81 0/subop/add %esp 8/imm32
10091     # . epilogue
10092     5d/pop-to-ebp
10093     c3/return
10094 
10095 test-compute-offset-with-no-inouts:
10096     # . prologue
10097     55/push-ebp
10098     89/<- %ebp 4/r32/esp
10099     # setup
10100     (clear-stream _test-input-stream)
10101     (clear-stream $_test-input-buffered-file->buffer)
10102     (clear-stream _test-output-stream)
10103     (clear-stream $_test-output-buffered-file->buffer)
10104     (clear-stream _test-error-stream)
10105     (clear-stream $_test-error-buffered-file->buffer)
10106     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10107     68/push 0/imm32
10108     68/push 0/imm32
10109     89/<- %edx 4/r32/esp
10110     (tailor-exit-descriptor %edx 0x10)
10111     #
10112     (write _test-input-stream "fn foo {\n")
10113     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
10114     (write _test-input-stream "}\n")
10115     # convert
10116     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10117     # registers except esp clobbered at this point
10118     # restore ed
10119     89/<- %edx 4/r32/esp
10120     (flush _test-output-buffered-file)
10121     (flush _test-error-buffered-file)
10122 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10128     # check output
10129     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
10130     (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")
10131     # check that stop(1) was called
10132     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
10133     # don't restore from ebp
10134     81 0/subop/add %esp 8/imm32
10135     # . epilogue
10136     5d/pop-to-ebp
10137     c3/return
10138 
10139 test-compute-offset-with-too-few-inouts:
10140     # . prologue
10141     55/push-ebp
10142     89/<- %ebp 4/r32/esp
10143     # setup
10144     (clear-stream _test-input-stream)
10145     (clear-stream $_test-input-buffered-file->buffer)
10146     (clear-stream _test-output-stream)
10147     (clear-stream $_test-output-buffered-file->buffer)
10148     (clear-stream _test-error-stream)
10149     (clear-stream $_test-error-buffered-file->buffer)
10150     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10151     68/push 0/imm32
10152     68/push 0/imm32
10153     89/<- %edx 4/r32/esp
10154     (tailor-exit-descriptor %edx 0x10)
10155     #
10156     (write _test-input-stream "fn foo {\n")
10157     (write _test-input-stream "  var a: (array int 3)\n")
10158     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
10159     (write _test-input-stream "}\n")
10160     # convert
10161     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10162     # registers except esp clobbered at this point
10163     # restore ed
10164     89/<- %edx 4/r32/esp
10165     (flush _test-output-buffered-file)
10166     (flush _test-error-buffered-file)
10167 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10173     # check output
10174     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
10175     (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")
10176     # check that stop(1) was called
10177     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
10178     # don't restore from ebp
10179     81 0/subop/add %esp 8/imm32
10180     # . epilogue
10181     5d/pop-to-ebp
10182     c3/return
10183 
10184 test-compute-offset-with-too-many-inouts:
10185     # . prologue
10186     55/push-ebp
10187     89/<- %ebp 4/r32/esp
10188     # setup
10189     (clear-stream _test-input-stream)
10190     (clear-stream $_test-input-buffered-file->buffer)
10191     (clear-stream _test-output-stream)
10192     (clear-stream $_test-output-buffered-file->buffer)
10193     (clear-stream _test-error-stream)
10194     (clear-stream $_test-error-buffered-file->buffer)
10195     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10196     68/push 0/imm32
10197     68/push 0/imm32
10198     89/<- %edx 4/r32/esp
10199     (tailor-exit-descriptor %edx 0x10)
10200     #
10201     (write _test-input-stream "fn foo {\n")
10202     (write _test-input-stream "  var a: (array int 3)\n")
10203     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
10204     (write _test-input-stream "}\n")
10205     # convert
10206     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10207     # registers except esp clobbered at this point
10208     # restore ed
10209     89/<- %edx 4/r32/esp
10210     (flush _test-output-buffered-file)
10211     (flush _test-error-buffered-file)
10212 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10218     # check output
10219     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
10220     (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")
10221     # check that stop(1) was called
10222     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
10223     # don't restore from ebp
10224     81 0/subop/add %esp 8/imm32
10225     # . epilogue
10226     5d/pop-to-ebp
10227     c3/return
10228 
10229 test-compute-offset-with-no-output:
10230     # . prologue
10231     55/push-ebp
10232     89/<- %ebp 4/r32/esp
10233     # setup
10234     (clear-stream _test-input-stream)
10235     (clear-stream $_test-input-buffered-file->buffer)
10236     (clear-stream _test-output-stream)
10237     (clear-stream $_test-output-buffered-file->buffer)
10238     (clear-stream _test-error-stream)
10239     (clear-stream $_test-error-buffered-file->buffer)
10240     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10241     68/push 0/imm32
10242     68/push 0/imm32
10243     89/<- %edx 4/r32/esp
10244     (tailor-exit-descriptor %edx 0x10)
10245     #
10246     (write _test-input-stream "fn foo {\n")
10247     (write _test-input-stream "  var a: (array int 3)\n")
10248     (write _test-input-stream "  compute-offset a, 0\n")
10249     (write _test-input-stream "}\n")
10250     # convert
10251     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10252     # registers except esp clobbered at this point
10253     # restore ed
10254     89/<- %edx 4/r32/esp
10255     (flush _test-output-buffered-file)
10256     (flush _test-error-buffered-file)
10257 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10263     # check output
10264     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
10265     (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")
10266     # check that stop(1) was called
10267     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
10268     # don't restore from ebp
10269     81 0/subop/add %esp 8/imm32
10270     # . epilogue
10271     5d/pop-to-ebp
10272     c3/return
10273 
10274 test-compute-offset-with-too-many-outputs:
10275     # . prologue
10276     55/push-ebp
10277     89/<- %ebp 4/r32/esp
10278     # setup
10279     (clear-stream _test-input-stream)
10280     (clear-stream $_test-input-buffered-file->buffer)
10281     (clear-stream _test-output-stream)
10282     (clear-stream $_test-output-buffered-file->buffer)
10283     (clear-stream _test-error-stream)
10284     (clear-stream $_test-error-buffered-file->buffer)
10285     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10286     68/push 0/imm32
10287     68/push 0/imm32
10288     89/<- %edx 4/r32/esp
10289     (tailor-exit-descriptor %edx 0x10)
10290     #
10291     (write _test-input-stream "fn foo {\n")
10292     (write _test-input-stream "  var a: (array int 3)\n")
10293     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
10294     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
10295     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
10296     (write _test-input-stream "}\n")
10297     # convert
10298     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10299     # registers except esp clobbered at this point
10300     # restore ed
10301     89/<- %edx 4/r32/esp
10302     (flush _test-output-buffered-file)
10303     (flush _test-error-buffered-file)
10304 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10310     # check output
10311     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
10312     (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")
10313     # check that stop(1) was called
10314     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
10315     # don't restore from ebp
10316     81 0/subop/add %esp 8/imm32
10317     # . epilogue
10318     5d/pop-to-ebp
10319     c3/return
10320 
10321 test-convert-read-from-stream:
10322     # . prologue
10323     55/push-ebp
10324     89/<- %ebp 4/r32/esp
10325     # setup
10326     (clear-stream _test-input-stream)
10327     (clear-stream $_test-input-buffered-file->buffer)
10328     (clear-stream _test-output-stream)
10329     (clear-stream $_test-output-buffered-file->buffer)
10330     #
10331     (write _test-input-stream "fn foo {\n")
10332     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
10333     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
10334     (write _test-input-stream "  read-from-stream s, o\n")
10335     (write _test-input-stream "}\n")
10336     # convert
10337     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10338     # registers except esp clobbered at this point
10339     # restore ed
10340     89/<- %edx 4/r32/esp
10341     (flush _test-output-buffered-file)
10342     (flush _test-error-buffered-file)
10343 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
10349     # check output
10350     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
10351     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
10352     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
10353     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
10354     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
10355     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
10356     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
10357     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
10358     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
10359     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
10360     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
10361     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
10362     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
10363     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
10364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
10365     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
10366     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
10367     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
10368     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
10369     # . epilogue
10370     89/<- %esp 5/r32/ebp
10371     5d/pop-to-ebp
10372     c3/return
10373 
10374 test-convert-read-from-stream-with-correct-payload-size:
10375     # . prologue
10376     55/push-ebp
10377     89/<- %ebp 4/r32/esp
10378     # setup
10379     (clear-stream _test-input-stream)
10380     (clear-stream $_test-input-buffered-file->buffer)
10381     (clear-stream _test-output-stream)
10382     (clear-stream $_test-output-buffered-file->buffer)
10383     #
10384     (write _test-input-stream "fn foo {\n")
10385     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
10386     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
10387     (write _test-input-stream "  read-from-stream s, o\n")
10388     (write _test-input-stream "}\n")
10389     # convert
10390     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10391     # registers except esp clobbered at this point
10392     # restore ed
10393     89/<- %edx 4/r32/esp
10394     (flush _test-output-buffered-file)
10395     (flush _test-error-buffered-file)
10396 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
10402     # check output
10403     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
10404     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
10405     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
10406     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
10407     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
10408     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
10409     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
10410     (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")
10411     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
10412     (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")
10413     (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")
10414     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
10415     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
10416     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
10417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
10418     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
10419     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
10420     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
10421     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
10422     # . epilogue
10423     89/<- %esp 5/r32/ebp
10424     5d/pop-to-ebp
10425     c3/return
10426 
10427 test-read-from-stream-with-non-stream-atom-base-type:
10428     # . prologue
10429     55/push-ebp
10430     89/<- %ebp 4/r32/esp
10431     # setup
10432     (clear-stream _test-input-stream)
10433     (clear-stream $_test-input-buffered-file->buffer)
10434     (clear-stream _test-output-stream)
10435     (clear-stream $_test-output-buffered-file->buffer)
10436     (clear-stream _test-error-stream)
10437     (clear-stream $_test-error-buffered-file->buffer)
10438     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10439     68/push 0/imm32
10440     68/push 0/imm32
10441     89/<- %edx 4/r32/esp
10442     (tailor-exit-descriptor %edx 0x10)
10443     #
10444     (write _test-input-stream "fn foo {\n")
10445     (write _test-input-stream "  var a: int\n")
10446     (write _test-input-stream "  read-from-stream a, 0\n")
10447     (write _test-input-stream "}\n")
10448     # convert
10449     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10450     # registers except esp clobbered at this point
10451     # restore ed
10452     89/<- %edx 4/r32/esp
10453     (flush _test-output-buffered-file)
10454     (flush _test-error-buffered-file)
10455 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10461     # check output
10462     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
10463     (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")
10464     # check that stop(1) was called
10465     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
10466     # don't restore from ebp
10467     81 0/subop/add %esp 8/imm32
10468     # . epilogue
10469     5d/pop-to-ebp
10470     c3/return
10471 
10472 test-read-from-stream-with-non-stream-compound-base-type:
10473     # . prologue
10474     55/push-ebp
10475     89/<- %ebp 4/r32/esp
10476     # setup
10477     (clear-stream _test-input-stream)
10478     (clear-stream $_test-input-buffered-file->buffer)
10479     (clear-stream _test-output-stream)
10480     (clear-stream $_test-output-buffered-file->buffer)
10481     (clear-stream _test-error-stream)
10482     (clear-stream $_test-error-buffered-file->buffer)
10483     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10484     68/push 0/imm32
10485     68/push 0/imm32
10486     89/<- %edx 4/r32/esp
10487     (tailor-exit-descriptor %edx 0x10)
10488     #
10489     (write _test-input-stream "fn foo {\n")
10490     (write _test-input-stream "  var a: (handle int)\n")
10491     (write _test-input-stream "  read-from-stream a, 0\n")
10492     (write _test-input-stream "}\n")
10493     # convert
10494     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10495     # registers except esp clobbered at this point
10496     # restore ed
10497     89/<- %edx 4/r32/esp
10498     (flush _test-output-buffered-file)
10499     (flush _test-error-buffered-file)
10500 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10506     # check output
10507     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
10508     (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")
10509     # check that stop(1) was called
10510     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
10511     # don't restore from ebp
10512     81 0/subop/add %esp 8/imm32
10513     # . epilogue
10514     5d/pop-to-ebp
10515     c3/return
10516 
10517 test-read-from-stream-with-non-stream-compound-base-type-2:
10518     # . prologue
10519     55/push-ebp
10520     89/<- %ebp 4/r32/esp
10521     # setup
10522     (clear-stream _test-input-stream)
10523     (clear-stream $_test-input-buffered-file->buffer)
10524     (clear-stream _test-output-stream)
10525     (clear-stream $_test-output-buffered-file->buffer)
10526     (clear-stream _test-error-stream)
10527     (clear-stream $_test-error-buffered-file->buffer)
10528     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10529     68/push 0/imm32
10530     68/push 0/imm32
10531     89/<- %edx 4/r32/esp
10532     (tailor-exit-descriptor %edx 0x10)
10533     #
10534     (write _test-input-stream "fn foo {\n")
10535     (write _test-input-stream "  var a: (addr int)\n")
10536     (write _test-input-stream "  read-from-stream a, 0\n")
10537     (write _test-input-stream "}\n")
10538     # convert
10539     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10540     # registers except esp clobbered at this point
10541     # restore ed
10542     89/<- %edx 4/r32/esp
10543     (flush _test-output-buffered-file)
10544     (flush _test-error-buffered-file)
10545 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10551     # check output
10552     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
10553     (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")
10554     # check that stop(1) was called
10555     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
10556     # don't restore from ebp
10557     81 0/subop/add %esp 8/imm32
10558     # . epilogue
10559     5d/pop-to-ebp
10560     c3/return
10561 
10562 test-read-from-stream-with-stream-atom-base-type:
10563     # . prologue
10564     55/push-ebp
10565     89/<- %ebp 4/r32/esp
10566     # setup
10567     (clear-stream _test-input-stream)
10568     (clear-stream $_test-input-buffered-file->buffer)
10569     (clear-stream _test-output-stream)
10570     (clear-stream $_test-output-buffered-file->buffer)
10571     (clear-stream _test-error-stream)
10572     (clear-stream $_test-error-buffered-file->buffer)
10573     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10574     68/push 0/imm32
10575     68/push 0/imm32
10576     89/<- %edx 4/r32/esp
10577     (tailor-exit-descriptor %edx 0x10)
10578     #
10579     (write _test-input-stream "fn foo {\n")
10580     (write _test-input-stream "  var a: stream\n")
10581     (write _test-input-stream "  read-from-stream a, 0\n")
10582     (write _test-input-stream "}\n")
10583     # convert
10584     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10585     # registers except esp clobbered at this point
10586     # restore ed
10587     89/<- %edx 4/r32/esp
10588     (flush _test-output-buffered-file)
10589     (flush _test-error-buffered-file)
10590 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10596     # check output
10597     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
10598     (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")
10599     # check that stop(1) was called
10600     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
10601     # don't restore from ebp
10602     81 0/subop/add %esp 8/imm32
10603     # . epilogue
10604     5d/pop-to-ebp
10605     c3/return
10606 
10607 test-read-from-stream-with-wrong-index-type:
10608     # . prologue
10609     55/push-ebp
10610     89/<- %ebp 4/r32/esp
10611     # setup
10612     (clear-stream _test-input-stream)
10613     (clear-stream $_test-input-buffered-file->buffer)
10614     (clear-stream _test-output-stream)
10615     (clear-stream $_test-output-buffered-file->buffer)
10616     (clear-stream _test-error-stream)
10617     (clear-stream $_test-error-buffered-file->buffer)
10618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10619     68/push 0/imm32
10620     68/push 0/imm32
10621     89/<- %edx 4/r32/esp
10622     (tailor-exit-descriptor %edx 0x10)
10623     #
10624     (write _test-input-stream "fn foo {\n")
10625     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
10626     (write _test-input-stream "  var b: boolean\n")
10627     (write _test-input-stream "  read-from-stream a, b\n")
10628     (write _test-input-stream "}\n")
10629     # convert
10630     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10631     # registers except esp clobbered at this point
10632     # restore ed
10633     89/<- %edx 4/r32/esp
10634     (flush _test-output-buffered-file)
10635     (flush _test-error-buffered-file)
10636 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10642     # check output
10643     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
10644     (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")
10645     # check that stop(1) was called
10646     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
10647     # don't restore from ebp
10648     81 0/subop/add %esp 8/imm32
10649     # . epilogue
10650     5d/pop-to-ebp
10651     c3/return
10652 
10653 test-read-from-stream-with-no-inouts:
10654     # . prologue
10655     55/push-ebp
10656     89/<- %ebp 4/r32/esp
10657     # setup
10658     (clear-stream _test-input-stream)
10659     (clear-stream $_test-input-buffered-file->buffer)
10660     (clear-stream _test-output-stream)
10661     (clear-stream $_test-output-buffered-file->buffer)
10662     (clear-stream _test-error-stream)
10663     (clear-stream $_test-error-buffered-file->buffer)
10664     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10665     68/push 0/imm32
10666     68/push 0/imm32
10667     89/<- %edx 4/r32/esp
10668     (tailor-exit-descriptor %edx 0x10)
10669     #
10670     (write _test-input-stream "fn foo {\n")
10671     (write _test-input-stream "  read-from-stream\n")
10672     (write _test-input-stream "}\n")
10673     # convert
10674     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10675     # registers except esp clobbered at this point
10676     # restore ed
10677     89/<- %edx 4/r32/esp
10678     (flush _test-output-buffered-file)
10679     (flush _test-error-buffered-file)
10680 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10686     # check output
10687     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
10688     (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")
10689     # check that stop(1) was called
10690     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
10691     # don't restore from ebp
10692     81 0/subop/add %esp 8/imm32
10693     # . epilogue
10694     5d/pop-to-ebp
10695     c3/return
10696 
10697 test-read-from-stream-with-too-few-inouts:
10698     # . prologue
10699     55/push-ebp
10700     89/<- %ebp 4/r32/esp
10701     # setup
10702     (clear-stream _test-input-stream)
10703     (clear-stream $_test-input-buffered-file->buffer)
10704     (clear-stream _test-output-stream)
10705     (clear-stream $_test-output-buffered-file->buffer)
10706     (clear-stream _test-error-stream)
10707     (clear-stream $_test-error-buffered-file->buffer)
10708     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10709     68/push 0/imm32
10710     68/push 0/imm32
10711     89/<- %edx 4/r32/esp
10712     (tailor-exit-descriptor %edx 0x10)
10713     #
10714     (write _test-input-stream "fn foo {\n")
10715     (write _test-input-stream "  var a: (addr stream int)\n")
10716     (write _test-input-stream "  read-from-stream a\n")
10717     (write _test-input-stream "}\n")
10718     # convert
10719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10720     # registers except esp clobbered at this point
10721     # restore ed
10722     89/<- %edx 4/r32/esp
10723     (flush _test-output-buffered-file)
10724     (flush _test-error-buffered-file)
10725 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10731     # check output
10732     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
10733     (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")
10734     # check that stop(1) was called
10735     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
10736     # don't restore from ebp
10737     81 0/subop/add %esp 8/imm32
10738     # . epilogue
10739     5d/pop-to-ebp
10740     c3/return
10741 
10742 test-read-from-stream-with-too-many-inouts:
10743     # . prologue
10744     55/push-ebp
10745     89/<- %ebp 4/r32/esp
10746     # setup
10747     (clear-stream _test-input-stream)
10748     (clear-stream $_test-input-buffered-file->buffer)
10749     (clear-stream _test-output-stream)
10750     (clear-stream $_test-output-buffered-file->buffer)
10751     (clear-stream _test-error-stream)
10752     (clear-stream $_test-error-buffered-file->buffer)
10753     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10754     68/push 0/imm32
10755     68/push 0/imm32
10756     89/<- %edx 4/r32/esp
10757     (tailor-exit-descriptor %edx 0x10)
10758     #
10759     (write _test-input-stream "fn foo {\n")
10760     (write _test-input-stream "  var a: (addr stream int)\n")
10761     (write _test-input-stream "  var b: (addr int)\n")
10762     (write _test-input-stream "  read-from-stream a, b, 0\n")
10763     (write _test-input-stream "}\n")
10764     # convert
10765     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10766     # registers except esp clobbered at this point
10767     # restore ed
10768     89/<- %edx 4/r32/esp
10769     (flush _test-output-buffered-file)
10770     (flush _test-error-buffered-file)
10771 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10777     # check output
10778     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
10779     (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")
10780     # check that stop(1) was called
10781     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
10782     # don't restore from ebp
10783     81 0/subop/add %esp 8/imm32
10784     # . epilogue
10785     5d/pop-to-ebp
10786     c3/return
10787 
10788 test-read-from-stream-with-output:
10789     # . prologue
10790     55/push-ebp
10791     89/<- %ebp 4/r32/esp
10792     # setup
10793     (clear-stream _test-input-stream)
10794     (clear-stream $_test-input-buffered-file->buffer)
10795     (clear-stream _test-output-stream)
10796     (clear-stream $_test-output-buffered-file->buffer)
10797     (clear-stream _test-error-stream)
10798     (clear-stream $_test-error-buffered-file->buffer)
10799     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10800     68/push 0/imm32
10801     68/push 0/imm32
10802     89/<- %edx 4/r32/esp
10803     (tailor-exit-descriptor %edx 0x10)
10804     #
10805     (write _test-input-stream "fn foo {\n")
10806     (write _test-input-stream "  var a: (addr stream int)\n")
10807     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
10808     (write _test-input-stream "  b <- read-from-stream a, b\n")
10809     (write _test-input-stream "}\n")
10810     # convert
10811     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10812     # registers except esp clobbered at this point
10813     # restore ed
10814     89/<- %edx 4/r32/esp
10815     (flush _test-output-buffered-file)
10816     (flush _test-error-buffered-file)
10817 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10823     # check output
10824     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
10825     (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")
10826     # check that stop(1) was called
10827     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
10828     # don't restore from ebp
10829     81 0/subop/add %esp 8/imm32
10830     # . epilogue
10831     5d/pop-to-ebp
10832     c3/return
10833 
10834 test-convert-write-to-stream:
10835     # . prologue
10836     55/push-ebp
10837     89/<- %ebp 4/r32/esp
10838     # setup
10839     (clear-stream _test-input-stream)
10840     (clear-stream $_test-input-buffered-file->buffer)
10841     (clear-stream _test-output-stream)
10842     (clear-stream $_test-output-buffered-file->buffer)
10843     #
10844     (write _test-input-stream "fn foo {\n")
10845     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
10846     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
10847     (write _test-input-stream "  write-to-stream s, o\n")
10848     (write _test-input-stream "}\n")
10849     # convert
10850     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10851     # registers except esp clobbered at this point
10852     # restore ed
10853     89/<- %edx 4/r32/esp
10854     (flush _test-output-buffered-file)
10855     (flush _test-error-buffered-file)
10856 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
10862     # check output
10863     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
10864     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
10865     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
10866     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
10867     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
10868     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
10869     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
10870     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
10871     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
10872     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
10873     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
10874     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
10875     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
10876     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
10877     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
10878     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
10879     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
10880     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
10881     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
10882     # . epilogue
10883     89/<- %esp 5/r32/ebp
10884     5d/pop-to-ebp
10885     c3/return
10886 
10887 test-convert-write-to-stream-with-correct-payload-size:
10888     # . prologue
10889     55/push-ebp
10890     89/<- %ebp 4/r32/esp
10891     # setup
10892     (clear-stream _test-input-stream)
10893     (clear-stream $_test-input-buffered-file->buffer)
10894     (clear-stream _test-output-stream)
10895     (clear-stream $_test-output-buffered-file->buffer)
10896     #
10897     (write _test-input-stream "fn foo {\n")
10898     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
10899     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
10900     (write _test-input-stream "  write-to-stream s, o\n")
10901     (write _test-input-stream "}\n")
10902     # convert
10903     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10904     # registers except esp clobbered at this point
10905     # restore ed
10906     89/<- %edx 4/r32/esp
10907     (flush _test-output-buffered-file)
10908     (flush _test-error-buffered-file)
10909 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
10915     # check output
10916     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
10917     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
10918     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
10919     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
10920     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
10921     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
10922     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
10923     (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")
10924     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
10925     (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")
10926     (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")
10927     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
10928     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
10929     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
10930     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
10931     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
10932     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
10933     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
10934     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
10935     # . epilogue
10936     89/<- %esp 5/r32/ebp
10937     5d/pop-to-ebp
10938     c3/return
10939 
10940 test-write-to-stream-with-non-stream-atom-base-type:
10941     # . prologue
10942     55/push-ebp
10943     89/<- %ebp 4/r32/esp
10944     # setup
10945     (clear-stream _test-input-stream)
10946     (clear-stream $_test-input-buffered-file->buffer)
10947     (clear-stream _test-output-stream)
10948     (clear-stream $_test-output-buffered-file->buffer)
10949     (clear-stream _test-error-stream)
10950     (clear-stream $_test-error-buffered-file->buffer)
10951     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10952     68/push 0/imm32
10953     68/push 0/imm32
10954     89/<- %edx 4/r32/esp
10955     (tailor-exit-descriptor %edx 0x10)
10956     #
10957     (write _test-input-stream "fn foo {\n")
10958     (write _test-input-stream "  var a: int\n")
10959     (write _test-input-stream "  write-to-stream a, 0\n")
10960     (write _test-input-stream "}\n")
10961     # convert
10962     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10963     # registers except esp clobbered at this point
10964     # restore ed
10965     89/<- %edx 4/r32/esp
10966     (flush _test-output-buffered-file)
10967     (flush _test-error-buffered-file)
10968 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
10974     # check output
10975     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
10976     (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")
10977     # check that stop(1) was called
10978     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
10979     # don't restore from ebp
10980     81 0/subop/add %esp 8/imm32
10981     # . epilogue
10982     5d/pop-to-ebp
10983     c3/return
10984 
10985 test-write-to-stream-with-non-stream-compound-base-type:
10986     # . prologue
10987     55/push-ebp
10988     89/<- %ebp 4/r32/esp
10989     # setup
10990     (clear-stream _test-input-stream)
10991     (clear-stream $_test-input-buffered-file->buffer)
10992     (clear-stream _test-output-stream)
10993     (clear-stream $_test-output-buffered-file->buffer)
10994     (clear-stream _test-error-stream)
10995     (clear-stream $_test-error-buffered-file->buffer)
10996     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10997     68/push 0/imm32
10998     68/push 0/imm32
10999     89/<- %edx 4/r32/esp
11000     (tailor-exit-descriptor %edx 0x10)
11001     #
11002     (write _test-input-stream "fn foo {\n")
11003     (write _test-input-stream "  var a: (handle int)\n")
11004     (write _test-input-stream "  write-to-stream a, 0\n")
11005     (write _test-input-stream "}\n")
11006     # convert
11007     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11008     # registers except esp clobbered at this point
11009     # restore ed
11010     89/<- %edx 4/r32/esp
11011     (flush _test-output-buffered-file)
11012     (flush _test-error-buffered-file)
11013 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11019     # check output
11020     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
11021     (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")
11022     # check that stop(1) was called
11023     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
11024     # don't restore from ebp
11025     81 0/subop/add %esp 8/imm32
11026     # . epilogue
11027     5d/pop-to-ebp
11028     c3/return
11029 
11030 test-write-to-stream-with-non-stream-compound-base-type-2:
11031     # . prologue
11032     55/push-ebp
11033     89/<- %ebp 4/r32/esp
11034     # setup
11035     (clear-stream _test-input-stream)
11036     (clear-stream $_test-input-buffered-file->buffer)
11037     (clear-stream _test-output-stream)
11038     (clear-stream $_test-output-buffered-file->buffer)
11039     (clear-stream _test-error-stream)
11040     (clear-stream $_test-error-buffered-file->buffer)
11041     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11042     68/push 0/imm32
11043     68/push 0/imm32
11044     89/<- %edx 4/r32/esp
11045     (tailor-exit-descriptor %edx 0x10)
11046     #
11047     (write _test-input-stream "fn foo {\n")
11048     (write _test-input-stream "  var a: (addr int)\n")
11049     (write _test-input-stream "  write-to-stream a, 0\n")
11050     (write _test-input-stream "}\n")
11051     # convert
11052     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11053     # registers except esp clobbered at this point
11054     # restore ed
11055     89/<- %edx 4/r32/esp
11056     (flush _test-output-buffered-file)
11057     (flush _test-error-buffered-file)
11058 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11064     # check output
11065     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
11066     (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")
11067     # check that stop(1) was called
11068     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
11069     # don't restore from ebp
11070     81 0/subop/add %esp 8/imm32
11071     # . epilogue
11072     5d/pop-to-ebp
11073     c3/return
11074 
11075 test-write-to-stream-with-stream-atom-base-type:
11076     # . prologue
11077     55/push-ebp
11078     89/<- %ebp 4/r32/esp
11079     # setup
11080     (clear-stream _test-input-stream)
11081     (clear-stream $_test-input-buffered-file->buffer)
11082     (clear-stream _test-output-stream)
11083     (clear-stream $_test-output-buffered-file->buffer)
11084     (clear-stream _test-error-stream)
11085     (clear-stream $_test-error-buffered-file->buffer)
11086     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11087     68/push 0/imm32
11088     68/push 0/imm32
11089     89/<- %edx 4/r32/esp
11090     (tailor-exit-descriptor %edx 0x10)
11091     #
11092     (write _test-input-stream "fn foo {\n")
11093     (write _test-input-stream "  var a: stream\n")
11094     (write _test-input-stream "  write-to-stream a, 0\n")
11095     (write _test-input-stream "}\n")
11096     # convert
11097     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11098     # registers except esp clobbered at this point
11099     # restore ed
11100     89/<- %edx 4/r32/esp
11101     (flush _test-output-buffered-file)
11102     (flush _test-error-buffered-file)
11103 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11109     # check output
11110     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
11111     (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")
11112     # check that stop(1) was called
11113     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
11114     # don't restore from ebp
11115     81 0/subop/add %esp 8/imm32
11116     # . epilogue
11117     5d/pop-to-ebp
11118     c3/return
11119 
11120 test-write-to-stream-with-wrong-index-type:
11121     # . prologue
11122     55/push-ebp
11123     89/<- %ebp 4/r32/esp
11124     # setup
11125     (clear-stream _test-input-stream)
11126     (clear-stream $_test-input-buffered-file->buffer)
11127     (clear-stream _test-output-stream)
11128     (clear-stream $_test-output-buffered-file->buffer)
11129     (clear-stream _test-error-stream)
11130     (clear-stream $_test-error-buffered-file->buffer)
11131     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11132     68/push 0/imm32
11133     68/push 0/imm32
11134     89/<- %edx 4/r32/esp
11135     (tailor-exit-descriptor %edx 0x10)
11136     #
11137     (write _test-input-stream "fn foo {\n")
11138     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
11139     (write _test-input-stream "  var b: boolean\n")
11140     (write _test-input-stream "  write-to-stream a, b\n")
11141     (write _test-input-stream "}\n")
11142     # convert
11143     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11144     # registers except esp clobbered at this point
11145     # restore ed
11146     89/<- %edx 4/r32/esp
11147     (flush _test-output-buffered-file)
11148     (flush _test-error-buffered-file)
11149 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11155     # check output
11156     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
11157     (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")
11158     # check that stop(1) was called
11159     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
11160     # don't restore from ebp
11161     81 0/subop/add %esp 8/imm32
11162     # . epilogue
11163     5d/pop-to-ebp
11164     c3/return
11165 
11166 test-write-to-stream-with-no-inouts:
11167     # . prologue
11168     55/push-ebp
11169     89/<- %ebp 4/r32/esp
11170     # setup
11171     (clear-stream _test-input-stream)
11172     (clear-stream $_test-input-buffered-file->buffer)
11173     (clear-stream _test-output-stream)
11174     (clear-stream $_test-output-buffered-file->buffer)
11175     (clear-stream _test-error-stream)
11176     (clear-stream $_test-error-buffered-file->buffer)
11177     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11178     68/push 0/imm32
11179     68/push 0/imm32
11180     89/<- %edx 4/r32/esp
11181     (tailor-exit-descriptor %edx 0x10)
11182     #
11183     (write _test-input-stream "fn foo {\n")
11184     (write _test-input-stream "  write-to-stream\n")
11185     (write _test-input-stream "}\n")
11186     # convert
11187     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11188     # registers except esp clobbered at this point
11189     # restore ed
11190     89/<- %edx 4/r32/esp
11191     (flush _test-output-buffered-file)
11192     (flush _test-error-buffered-file)
11193 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11199     # check output
11200     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
11201     (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")
11202     # check that stop(1) was called
11203     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
11204     # don't restore from ebp
11205     81 0/subop/add %esp 8/imm32
11206     # . epilogue
11207     5d/pop-to-ebp
11208     c3/return
11209 
11210 test-write-to-stream-with-too-few-inouts:
11211     # . prologue
11212     55/push-ebp
11213     89/<- %ebp 4/r32/esp
11214     # setup
11215     (clear-stream _test-input-stream)
11216     (clear-stream $_test-input-buffered-file->buffer)
11217     (clear-stream _test-output-stream)
11218     (clear-stream $_test-output-buffered-file->buffer)
11219     (clear-stream _test-error-stream)
11220     (clear-stream $_test-error-buffered-file->buffer)
11221     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11222     68/push 0/imm32
11223     68/push 0/imm32
11224     89/<- %edx 4/r32/esp
11225     (tailor-exit-descriptor %edx 0x10)
11226     #
11227     (write _test-input-stream "fn foo {\n")
11228     (write _test-input-stream "  var a: (addr stream int)\n")
11229     (write _test-input-stream "  write-to-stream a\n")
11230     (write _test-input-stream "}\n")
11231     # convert
11232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11233     # registers except esp clobbered at this point
11234     # restore ed
11235     89/<- %edx 4/r32/esp
11236     (flush _test-output-buffered-file)
11237     (flush _test-error-buffered-file)
11238 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11244     # check output
11245     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
11246     (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")
11247     # check that stop(1) was called
11248     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
11249     # don't restore from ebp
11250     81 0/subop/add %esp 8/imm32
11251     # . epilogue
11252     5d/pop-to-ebp
11253     c3/return
11254 
11255 test-write-to-stream-with-too-many-inouts:
11256     # . prologue
11257     55/push-ebp
11258     89/<- %ebp 4/r32/esp
11259     # setup
11260     (clear-stream _test-input-stream)
11261     (clear-stream $_test-input-buffered-file->buffer)
11262     (clear-stream _test-output-stream)
11263     (clear-stream $_test-output-buffered-file->buffer)
11264     (clear-stream _test-error-stream)
11265     (clear-stream $_test-error-buffered-file->buffer)
11266     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11267     68/push 0/imm32
11268     68/push 0/imm32
11269     89/<- %edx 4/r32/esp
11270     (tailor-exit-descriptor %edx 0x10)
11271     #
11272     (write _test-input-stream "fn foo {\n")
11273     (write _test-input-stream "  var a: (addr stream int)\n")
11274     (write _test-input-stream "  var b: (addr int)\n")
11275     (write _test-input-stream "  write-to-stream a, b, 0\n")
11276     (write _test-input-stream "}\n")
11277     # convert
11278     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11279     # registers except esp clobbered at this point
11280     # restore ed
11281     89/<- %edx 4/r32/esp
11282     (flush _test-output-buffered-file)
11283     (flush _test-error-buffered-file)
11284 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11290     # check output
11291     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
11292     (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")
11293     # check that stop(1) was called
11294     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
11295     # don't restore from ebp
11296     81 0/subop/add %esp 8/imm32
11297     # . epilogue
11298     5d/pop-to-ebp
11299     c3/return
11300 
11301 test-write-to-stream-with-output:
11302     # . prologue
11303     55/push-ebp
11304     89/<- %ebp 4/r32/esp
11305     # setup
11306     (clear-stream _test-input-stream)
11307     (clear-stream $_test-input-buffered-file->buffer)
11308     (clear-stream _test-output-stream)
11309     (clear-stream $_test-output-buffered-file->buffer)
11310     (clear-stream _test-error-stream)
11311     (clear-stream $_test-error-buffered-file->buffer)
11312     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11313     68/push 0/imm32
11314     68/push 0/imm32
11315     89/<- %edx 4/r32/esp
11316     (tailor-exit-descriptor %edx 0x10)
11317     #
11318     (write _test-input-stream "fn foo {\n")
11319     (write _test-input-stream "  var a: (addr stream int)\n")
11320     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11321     (write _test-input-stream "  b <- write-to-stream a, b\n")
11322     (write _test-input-stream "}\n")
11323     # convert
11324     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11325     # registers except esp clobbered at this point
11326     # restore ed
11327     89/<- %edx 4/r32/esp
11328     (flush _test-output-buffered-file)
11329     (flush _test-error-buffered-file)
11330 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11336     # check output
11337     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
11338     (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")
11339     # check that stop(1) was called
11340     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
11341     # don't restore from ebp
11342     81 0/subop/add %esp 8/imm32
11343     # . epilogue
11344     5d/pop-to-ebp
11345     c3/return
11346 
11347 test-length-with-non-array-atom-base-type:
11348     # . prologue
11349     55/push-ebp
11350     89/<- %ebp 4/r32/esp
11351     # setup
11352     (clear-stream _test-input-stream)
11353     (clear-stream $_test-input-buffered-file->buffer)
11354     (clear-stream _test-output-stream)
11355     (clear-stream $_test-output-buffered-file->buffer)
11356     (clear-stream _test-error-stream)
11357     (clear-stream $_test-error-buffered-file->buffer)
11358     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11359     68/push 0/imm32
11360     68/push 0/imm32
11361     89/<- %edx 4/r32/esp
11362     (tailor-exit-descriptor %edx 0x10)
11363     #
11364     (write _test-input-stream "fn foo {\n")
11365     (write _test-input-stream "  var a: int\n")
11366     (write _test-input-stream "  var c/ecx: int <- length a\n")
11367     (write _test-input-stream "}\n")
11368     # convert
11369     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11370     # registers except esp clobbered at this point
11371     # restore ed
11372     89/<- %edx 4/r32/esp
11373     (flush _test-output-buffered-file)
11374     (flush _test-error-buffered-file)
11375 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11381     # check output
11382     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
11383     (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")
11384     # check that stop(1) was called
11385     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
11386     # don't restore from ebp
11387     81 0/subop/add %esp 8/imm32
11388     # . epilogue
11389     5d/pop-to-ebp
11390     c3/return
11391 
11392 test-length-with-non-array-compound-base-type:
11393     # . prologue
11394     55/push-ebp
11395     89/<- %ebp 4/r32/esp
11396     # setup
11397     (clear-stream _test-input-stream)
11398     (clear-stream $_test-input-buffered-file->buffer)
11399     (clear-stream _test-output-stream)
11400     (clear-stream $_test-output-buffered-file->buffer)
11401     (clear-stream _test-error-stream)
11402     (clear-stream $_test-error-buffered-file->buffer)
11403     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11404     68/push 0/imm32
11405     68/push 0/imm32
11406     89/<- %edx 4/r32/esp
11407     (tailor-exit-descriptor %edx 0x10)
11408     #
11409     (write _test-input-stream "fn foo {\n")
11410     (write _test-input-stream "  var a: (handle int)\n")
11411     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
11412     (write _test-input-stream "}\n")
11413     # convert
11414     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11415     # registers except esp clobbered at this point
11416     # restore ed
11417     89/<- %edx 4/r32/esp
11418     (flush _test-output-buffered-file)
11419     (flush _test-error-buffered-file)
11420 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11426     # check output
11427     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
11428     (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")
11429     # check that stop(1) was called
11430     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
11431     # don't restore from ebp
11432     81 0/subop/add %esp 8/imm32
11433     # . epilogue
11434     5d/pop-to-ebp
11435     c3/return
11436 
11437 test-length-with-non-array-compound-base-type-2:
11438     # . prologue
11439     55/push-ebp
11440     89/<- %ebp 4/r32/esp
11441     # setup
11442     (clear-stream _test-input-stream)
11443     (clear-stream $_test-input-buffered-file->buffer)
11444     (clear-stream _test-output-stream)
11445     (clear-stream $_test-output-buffered-file->buffer)
11446     (clear-stream _test-error-stream)
11447     (clear-stream $_test-error-buffered-file->buffer)
11448     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11449     68/push 0/imm32
11450     68/push 0/imm32
11451     89/<- %edx 4/r32/esp
11452     (tailor-exit-descriptor %edx 0x10)
11453     #
11454     (write _test-input-stream "fn foo {\n")
11455     (write _test-input-stream "  var a: (addr int)\n")
11456     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
11457     (write _test-input-stream "}\n")
11458     # convert
11459     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11460     # registers except esp clobbered at this point
11461     # restore ed
11462     89/<- %edx 4/r32/esp
11463     (flush _test-output-buffered-file)
11464     (flush _test-error-buffered-file)
11465 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11471     # check output
11472     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
11473     (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")
11474     # check that stop(1) was called
11475     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
11476     # don't restore from ebp
11477     81 0/subop/add %esp 8/imm32
11478     # . epilogue
11479     5d/pop-to-ebp
11480     c3/return
11481 
11482 test-length-with-array-atom-base-type:
11483     # . prologue
11484     55/push-ebp
11485     89/<- %ebp 4/r32/esp
11486     # setup
11487     (clear-stream _test-input-stream)
11488     (clear-stream $_test-input-buffered-file->buffer)
11489     (clear-stream _test-output-stream)
11490     (clear-stream $_test-output-buffered-file->buffer)
11491     (clear-stream _test-error-stream)
11492     (clear-stream $_test-error-buffered-file->buffer)
11493     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11494     68/push 0/imm32
11495     68/push 0/imm32
11496     89/<- %edx 4/r32/esp
11497     (tailor-exit-descriptor %edx 0x10)
11498     #
11499     (write _test-input-stream "fn foo {\n")
11500     (write _test-input-stream "  var a: array\n")
11501     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
11502     (write _test-input-stream "}\n")
11503     # convert
11504     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11505     # registers except esp clobbered at this point
11506     # restore ed
11507     89/<- %edx 4/r32/esp
11508     (flush _test-output-buffered-file)
11509     (flush _test-error-buffered-file)
11510 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11516     # check output
11517     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
11518     (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")
11519     # check that stop(1) was called
11520     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
11521     # don't restore from ebp
11522     81 0/subop/add %esp 8/imm32
11523     # . epilogue
11524     5d/pop-to-ebp
11525     c3/return
11526 
11527 test-length-with-addr-base-on-stack:
11528     # . prologue
11529     55/push-ebp
11530     89/<- %ebp 4/r32/esp
11531     # setup
11532     (clear-stream _test-input-stream)
11533     (clear-stream $_test-input-buffered-file->buffer)
11534     (clear-stream _test-output-stream)
11535     (clear-stream $_test-output-buffered-file->buffer)
11536     (clear-stream _test-error-stream)
11537     (clear-stream $_test-error-buffered-file->buffer)
11538     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11539     68/push 0/imm32
11540     68/push 0/imm32
11541     89/<- %edx 4/r32/esp
11542     (tailor-exit-descriptor %edx 0x10)
11543     #
11544     (write _test-input-stream "fn foo {\n")
11545     (write _test-input-stream "  var a: (addr array int)\n")
11546     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
11547     (write _test-input-stream "}\n")
11548     # convert
11549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11550     # registers except esp clobbered at this point
11551     # restore ed
11552     89/<- %edx 4/r32/esp
11553     (flush _test-output-buffered-file)
11554     (flush _test-error-buffered-file)
11555 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11561     # check output
11562     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
11563     (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")
11564     # check that stop(1) was called
11565     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
11566     # don't restore from ebp
11567     81 0/subop/add %esp 8/imm32
11568     # . epilogue
11569     5d/pop-to-ebp
11570     c3/return
11571 
11572 test-length-with-wrong-output-type:
11573     # . prologue
11574     55/push-ebp
11575     89/<- %ebp 4/r32/esp
11576     # setup
11577     (clear-stream _test-input-stream)
11578     (clear-stream $_test-input-buffered-file->buffer)
11579     (clear-stream _test-output-stream)
11580     (clear-stream $_test-output-buffered-file->buffer)
11581     (clear-stream _test-error-stream)
11582     (clear-stream $_test-error-buffered-file->buffer)
11583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11584     68/push 0/imm32
11585     68/push 0/imm32
11586     89/<- %edx 4/r32/esp
11587     (tailor-exit-descriptor %edx 0x10)
11588     #
11589     (write _test-input-stream "fn foo {\n")
11590     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11591     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
11592     (write _test-input-stream "}\n")
11593     # convert
11594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11595     # registers except esp clobbered at this point
11596     # restore ed
11597     89/<- %edx 4/r32/esp
11598     (flush _test-output-buffered-file)
11599     (flush _test-error-buffered-file)
11600 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11606     # check output
11607     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
11608     (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")
11609     # check that stop(1) was called
11610     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
11611     # don't restore from ebp
11612     81 0/subop/add %esp 8/imm32
11613     # . epilogue
11614     5d/pop-to-ebp
11615     c3/return
11616 
11617 test-length-with-wrong-output-compound-type:
11618     # . prologue
11619     55/push-ebp
11620     89/<- %ebp 4/r32/esp
11621     # setup
11622     (clear-stream _test-input-stream)
11623     (clear-stream $_test-input-buffered-file->buffer)
11624     (clear-stream _test-output-stream)
11625     (clear-stream $_test-output-buffered-file->buffer)
11626     (clear-stream _test-error-stream)
11627     (clear-stream $_test-error-buffered-file->buffer)
11628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11629     68/push 0/imm32
11630     68/push 0/imm32
11631     89/<- %edx 4/r32/esp
11632     (tailor-exit-descriptor %edx 0x10)
11633     #
11634     (write _test-input-stream "fn foo {\n")
11635     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11636     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
11637     (write _test-input-stream "}\n")
11638     # convert
11639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11640     # registers except esp clobbered at this point
11641     # restore ed
11642     89/<- %edx 4/r32/esp
11643     (flush _test-output-buffered-file)
11644     (flush _test-error-buffered-file)
11645 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11651     # check output
11652     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
11653     (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")
11654     # check that stop(1) was called
11655     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
11656     # don't restore from ebp
11657     81 0/subop/add %esp 8/imm32
11658     # . epilogue
11659     5d/pop-to-ebp
11660     c3/return
11661 
11662 test-length-with-no-inouts:
11663     # . prologue
11664     55/push-ebp
11665     89/<- %ebp 4/r32/esp
11666     # setup
11667     (clear-stream _test-input-stream)
11668     (clear-stream $_test-input-buffered-file->buffer)
11669     (clear-stream _test-output-stream)
11670     (clear-stream $_test-output-buffered-file->buffer)
11671     (clear-stream _test-error-stream)
11672     (clear-stream $_test-error-buffered-file->buffer)
11673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11674     68/push 0/imm32
11675     68/push 0/imm32
11676     89/<- %edx 4/r32/esp
11677     (tailor-exit-descriptor %edx 0x10)
11678     #
11679     (write _test-input-stream "fn foo {\n")
11680     (write _test-input-stream "  var c/ecx: int <- length\n")
11681     (write _test-input-stream "}\n")
11682     # convert
11683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11684     # registers except esp clobbered at this point
11685     # restore ed
11686     89/<- %edx 4/r32/esp
11687     (flush _test-output-buffered-file)
11688     (flush _test-error-buffered-file)
11689 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11695     # check output
11696     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
11697     (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")
11698     # check that stop(1) was called
11699     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
11700     # don't restore from ebp
11701     81 0/subop/add %esp 8/imm32
11702     # . epilogue
11703     5d/pop-to-ebp
11704     c3/return
11705 
11706 test-length-with-too-many-inouts:
11707     # . prologue
11708     55/push-ebp
11709     89/<- %ebp 4/r32/esp
11710     # setup
11711     (clear-stream _test-input-stream)
11712     (clear-stream $_test-input-buffered-file->buffer)
11713     (clear-stream _test-output-stream)
11714     (clear-stream $_test-output-buffered-file->buffer)
11715     (clear-stream _test-error-stream)
11716     (clear-stream $_test-error-buffered-file->buffer)
11717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11718     68/push 0/imm32
11719     68/push 0/imm32
11720     89/<- %edx 4/r32/esp
11721     (tailor-exit-descriptor %edx 0x10)
11722     #
11723     (write _test-input-stream "fn foo {\n")
11724     (write _test-input-stream "  var a: (array int 3)\n")
11725     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
11726     (write _test-input-stream "}\n")
11727     # convert
11728     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11729     # registers except esp clobbered at this point
11730     # restore ed
11731     89/<- %edx 4/r32/esp
11732     (flush _test-output-buffered-file)
11733     (flush _test-error-buffered-file)
11734 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11740     # check output
11741     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
11742     (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")
11743     # check that stop(1) was called
11744     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
11745     # don't restore from ebp
11746     81 0/subop/add %esp 8/imm32
11747     # . epilogue
11748     5d/pop-to-ebp
11749     c3/return
11750 
11751 test-length-with-no-output:
11752     # . prologue
11753     55/push-ebp
11754     89/<- %ebp 4/r32/esp
11755     # setup
11756     (clear-stream _test-input-stream)
11757     (clear-stream $_test-input-buffered-file->buffer)
11758     (clear-stream _test-output-stream)
11759     (clear-stream $_test-output-buffered-file->buffer)
11760     (clear-stream _test-error-stream)
11761     (clear-stream $_test-error-buffered-file->buffer)
11762     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11763     68/push 0/imm32
11764     68/push 0/imm32
11765     89/<- %edx 4/r32/esp
11766     (tailor-exit-descriptor %edx 0x10)
11767     #
11768     (write _test-input-stream "fn foo {\n")
11769     (write _test-input-stream "  var a: (array int 3)\n")
11770     (write _test-input-stream "  length a\n")
11771     (write _test-input-stream "}\n")
11772     # convert
11773     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11774     # registers except esp clobbered at this point
11775     # restore ed
11776     89/<- %edx 4/r32/esp
11777     (flush _test-output-buffered-file)
11778     (flush _test-error-buffered-file)
11779 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11785     # check output
11786     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
11787     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
11788     # check that stop(1) was called
11789     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
11790     # don't restore from ebp
11791     81 0/subop/add %esp 8/imm32
11792     # . epilogue
11793     5d/pop-to-ebp
11794     c3/return
11795 
11796 test-length-with-too-many-outputs:
11797     # . prologue
11798     55/push-ebp
11799     89/<- %ebp 4/r32/esp
11800     # setup
11801     (clear-stream _test-input-stream)
11802     (clear-stream $_test-input-buffered-file->buffer)
11803     (clear-stream _test-output-stream)
11804     (clear-stream $_test-output-buffered-file->buffer)
11805     (clear-stream _test-error-stream)
11806     (clear-stream $_test-error-buffered-file->buffer)
11807     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11808     68/push 0/imm32
11809     68/push 0/imm32
11810     89/<- %edx 4/r32/esp
11811     (tailor-exit-descriptor %edx 0x10)
11812     #
11813     (write _test-input-stream "fn foo {\n")
11814     (write _test-input-stream "  var a: (array int 3)\n")
11815     (write _test-input-stream "  var b/eax: int <- copy 0\n")
11816     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
11817     (write _test-input-stream "  b, c <- length a\n")
11818     (write _test-input-stream "}\n")
11819     # convert
11820     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11821     # registers except esp clobbered at this point
11822     # restore ed
11823     89/<- %edx 4/r32/esp
11824     (flush _test-output-buffered-file)
11825     (flush _test-error-buffered-file)
11826 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
11832     # check output
11833     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
11834     (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")
11835     # check that stop(1) was called
11836     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
11837     # don't restore from ebp
11838     81 0/subop/add %esp 8/imm32
11839     # . epilogue
11840     5d/pop-to-ebp
11841     c3/return
11842 
11843 test-convert-function-with-return-register-and-local:
11844     # . prologue
11845     55/push-ebp
11846     89/<- %ebp 4/r32/esp
11847     # setup
11848     (clear-stream _test-input-stream)
11849     (clear-stream $_test-input-buffered-file->buffer)
11850     (clear-stream _test-output-stream)
11851     (clear-stream $_test-output-buffered-file->buffer)
11852     #
11853     (write _test-input-stream "fn foo -> _/eax: int {\n")
11854     (write _test-input-stream "  var y/eax: int <- copy 3\n")
11855     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
11856     (write _test-input-stream "  return y\n")
11857     (write _test-input-stream "}\n")
11858     # convert
11859     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11860     (flush _test-output-buffered-file)
11861 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
11867     # check output
11868     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
11869     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
11870     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
11871     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
11872     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
11873     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
11874     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
11875     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
11876     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
11877     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
11878     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
11879     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
11880     (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")
11881     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
11882     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
11883     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
11884     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
11885     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
11886     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
11887     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
11888     # . epilogue
11889     89/<- %esp 5/r32/ebp
11890     5d/pop-to-ebp
11891     c3/return
11892 
11893 test-convert-function-with-return-register-and-local-2:
11894     # . prologue
11895     55/push-ebp
11896     89/<- %ebp 4/r32/esp
11897     # setup
11898     (clear-stream _test-input-stream)
11899     (clear-stream $_test-input-buffered-file->buffer)
11900     (clear-stream _test-output-stream)
11901     (clear-stream $_test-output-buffered-file->buffer)
11902     #
11903     (write _test-input-stream "fn foo -> _/eax: int {\n")
11904     (write _test-input-stream "  var y/eax: int <- copy 3\n")
11905     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
11906     (write _test-input-stream "  return z\n")
11907     (write _test-input-stream "}\n")
11908     # convert
11909     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11910     (flush _test-output-buffered-file)
11911 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
11917     # check output
11918     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
11919     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
11920     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
11921     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
11922     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
11923     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
11924     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
11925     (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")
11926     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
11927     (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")
11928     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
11929     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
11930     (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")
11931     (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")
11932     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
11933     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
11934     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
11935     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
11936     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
11937     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
11938     # . epilogue
11939     89/<- %esp 5/r32/ebp
11940     5d/pop-to-ebp
11941     c3/return
11942 
11943 test-convert-function-with-return-float-register-and-local:
11944     # . prologue
11945     55/push-ebp
11946     89/<- %ebp 4/r32/esp
11947     # setup
11948     (clear-stream _test-input-stream)
11949     (clear-stream $_test-input-buffered-file->buffer)
11950     (clear-stream _test-output-stream)
11951     (clear-stream $_test-output-buffered-file->buffer)
11952     #
11953     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
11954     (write _test-input-stream "  var y/eax: int <- copy 3\n")
11955     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
11956     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
11957     (write _test-input-stream "  return g\n")
11958     (write _test-input-stream "}\n")
11959     # convert
11960     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11961     (flush _test-output-buffered-file)
11962 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
11968     # check output
11969     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
11970     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
11971     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
11972     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
11973     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
11974     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
11975     (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
11976     (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")
11977     (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
11978     (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")
11979     (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")
11980     (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
11981     (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")
11982     (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")
11983     (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
11984     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
11985     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
11986     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
11987     (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
11988     (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")
11989     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
11990     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
11991     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
11992     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
11993     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
11994     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
11995     # . epilogue
11996     89/<- %esp 5/r32/ebp
11997     5d/pop-to-ebp
11998     c3/return
11999 
12000 test-convert-function-with-return-and-local-vars:
12001     # . prologue
12002     55/push-ebp
12003     89/<- %ebp 4/r32/esp
12004     # setup
12005     (clear-stream _test-input-stream)
12006     (clear-stream $_test-input-buffered-file->buffer)
12007     (clear-stream _test-output-stream)
12008     (clear-stream $_test-output-buffered-file->buffer)
12009     #
12010     (write _test-input-stream "fn foo -> _/eax: int {\n")
12011     (write _test-input-stream "  {\n")
12012     (write _test-input-stream "    var x: int\n")
12013     (write _test-input-stream "    {\n")
12014     (write _test-input-stream "      var y: int\n")
12015     (write _test-input-stream "      return y\n")
12016     (write _test-input-stream "      increment x\n")
12017     (write _test-input-stream "    }\n")
12018     (write _test-input-stream "  }\n")
12019     (write _test-input-stream "  return 0\n")
12020     (write _test-input-stream "}\n")
12021     # convert
12022     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12023     (flush _test-output-buffered-file)
12024 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
12030     # check output
12031     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
12032     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
12033     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
12034     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
12035     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
12036     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
12037     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
12038     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
12039     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
12040     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
12041     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
12042     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
12043     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
12044     (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")
12045     (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")
12046     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
12047     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
12048     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
12049     (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")
12050     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
12051     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
12052     (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")
12053     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
12054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
12055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
12056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
12057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
12058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
12059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
12060     # . epilogue
12061     89/<- %esp 5/r32/ebp
12062     5d/pop-to-ebp
12063     c3/return
12064 
12065 test-copy-object-with-no-inout:
12066     # . prologue
12067     55/push-ebp
12068     89/<- %ebp 4/r32/esp
12069     # setup
12070     (clear-stream _test-input-stream)
12071     (clear-stream $_test-input-buffered-file->buffer)
12072     (clear-stream _test-output-stream)
12073     (clear-stream $_test-output-buffered-file->buffer)
12074     (clear-stream _test-error-stream)
12075     (clear-stream $_test-error-buffered-file->buffer)
12076     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12077     68/push 0/imm32
12078     68/push 0/imm32
12079     89/<- %edx 4/r32/esp
12080     (tailor-exit-descriptor %edx 0x10)
12081     #
12082     (write _test-input-stream "fn foo {\n")
12083     (write _test-input-stream "  copy-object\n")
12084     (write _test-input-stream "}\n")
12085     # convert
12086     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12087     # registers except esp clobbered at this point
12088     # restore ed
12089     89/<- %edx 4/r32/esp
12090     (flush _test-output-buffered-file)
12091     (flush _test-error-buffered-file)
12092 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12098     # check output
12099     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
12100     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
12101     # check that stop(1) was called
12102     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
12103     # don't restore from ebp
12104     81 0/subop/add %esp 8/imm32
12105     # . epilogue
12106     5d/pop-to-ebp
12107     c3/return
12108 
12109 test-copy-object-with-no-input:
12110     # . prologue
12111     55/push-ebp
12112     89/<- %ebp 4/r32/esp
12113     # setup
12114     (clear-stream _test-input-stream)
12115     (clear-stream $_test-input-buffered-file->buffer)
12116     (clear-stream _test-output-stream)
12117     (clear-stream $_test-output-buffered-file->buffer)
12118     (clear-stream _test-error-stream)
12119     (clear-stream $_test-error-buffered-file->buffer)
12120     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12121     68/push 0/imm32
12122     68/push 0/imm32
12123     89/<- %edx 4/r32/esp
12124     (tailor-exit-descriptor %edx 0x10)
12125     #
12126     (write _test-input-stream "fn foo {\n")
12127     (write _test-input-stream "  var x: (addr int)\n")
12128     (write _test-input-stream "  copy-object x\n")
12129     (write _test-input-stream "}\n")
12130     # convert
12131     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12132     # registers except esp clobbered at this point
12133     # restore ed
12134     89/<- %edx 4/r32/esp
12135     (flush _test-output-buffered-file)
12136     (flush _test-error-buffered-file)
12137 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12143     # check output
12144     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-input: output should be empty")
12145     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-input: error message")
12146     # check that stop(1) was called
12147     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-input: exit status")
12148     # don't restore from ebp
12149     81 0/subop/add %esp 8/imm32
12150     # . epilogue
12151     5d/pop-to-ebp
12152     c3/return
12153 
12154 test-copy-object-with-too-many-inouts:
12155     # . prologue
12156     55/push-ebp
12157     89/<- %ebp 4/r32/esp
12158     # setup
12159     (clear-stream _test-input-stream)
12160     (clear-stream $_test-input-buffered-file->buffer)
12161     (clear-stream _test-output-stream)
12162     (clear-stream $_test-output-buffered-file->buffer)
12163     (clear-stream _test-error-stream)
12164     (clear-stream $_test-error-buffered-file->buffer)
12165     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12166     68/push 0/imm32
12167     68/push 0/imm32
12168     89/<- %edx 4/r32/esp
12169     (tailor-exit-descriptor %edx 0x10)
12170     #
12171     (write _test-input-stream "fn foo {\n")
12172     (write _test-input-stream "  var x: (addr boolean)\n")
12173     (write _test-input-stream "  copy-object x, x, x\n")
12174     (write _test-input-stream "}\n")
12175     # convert
12176     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12177     # registers except esp clobbered at this point
12178     # restore ed
12179     89/<- %edx 4/r32/esp
12180     (flush _test-output-buffered-file)
12181     (flush _test-error-buffered-file)
12182 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12188     # check output
12189     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
12190     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-too-many-inouts: error message")
12191     # check that stop(1) was called
12192     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
12193     # don't restore from ebp
12194     81 0/subop/add %esp 8/imm32
12195     # . epilogue
12196     5d/pop-to-ebp
12197     c3/return
12198 
12199 test-copy-object-with-output:
12200     # . prologue
12201     55/push-ebp
12202     89/<- %ebp 4/r32/esp
12203     # setup
12204     (clear-stream _test-input-stream)
12205     (clear-stream $_test-input-buffered-file->buffer)
12206     (clear-stream _test-output-stream)
12207     (clear-stream $_test-output-buffered-file->buffer)
12208     (clear-stream _test-error-stream)
12209     (clear-stream $_test-error-buffered-file->buffer)
12210     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12211     68/push 0/imm32
12212     68/push 0/imm32
12213     89/<- %edx 4/r32/esp
12214     (tailor-exit-descriptor %edx 0x10)
12215     #
12216     (write _test-input-stream "fn foo {\n")
12217     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
12218     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
12219     (write _test-input-stream "  x <- copy-object x, y\n")
12220     (write _test-input-stream "}\n")
12221     # convert
12222     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12223     # registers except esp clobbered at this point
12224     # restore ed
12225     89/<- %edx 4/r32/esp
12226     (flush _test-output-buffered-file)
12227     (flush _test-error-buffered-file)
12228 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12234     # check output
12235     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
12236     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must not have any outputs"  "F - test-copy-object-with-output: error message")
12237     # check that stop(1) was called
12238     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
12239     # don't restore from ebp
12240     81 0/subop/add %esp 8/imm32
12241     # . epilogue
12242     5d/pop-to-ebp
12243     c3/return
12244 
12245 test-copy-object-deref-address:
12246     # . prologue
12247     55/push-ebp
12248     89/<- %ebp 4/r32/esp
12249     # setup
12250     (clear-stream _test-input-stream)
12251     (clear-stream $_test-input-buffered-file->buffer)
12252     (clear-stream _test-output-stream)
12253     (clear-stream $_test-output-buffered-file->buffer)
12254     #
12255     (write _test-input-stream "fn foo {\n")
12256     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
12257     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
12258     (write _test-input-stream "  copy-object *y, x\n")
12259     (write _test-input-stream "}\n")
12260     # convert
12261     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12262     (flush _test-output-buffered-file)
12263 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12269     # not bothering checking output
12270     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-object-deref-address: error message")
12271     # . epilogue
12272     5d/pop-to-ebp
12273     c3/return
12274 
12275 test-copy-object-non-addr:
12276     # . prologue
12277     55/push-ebp
12278     89/<- %ebp 4/r32/esp
12279     # setup
12280     (clear-stream _test-input-stream)
12281     (clear-stream $_test-input-buffered-file->buffer)
12282     (clear-stream _test-output-stream)
12283     (clear-stream $_test-output-buffered-file->buffer)
12284     (clear-stream _test-error-stream)
12285     (clear-stream $_test-error-buffered-file->buffer)
12286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12287     68/push 0/imm32
12288     68/push 0/imm32
12289     89/<- %edx 4/r32/esp
12290     (tailor-exit-descriptor %edx 0x10)
12291     #
12292     (write _test-input-stream "fn foo {\n")
12293     (write _test-input-stream "  var x: int\n")
12294     (write _test-input-stream "  var y: int\n")
12295     (write _test-input-stream "  copy-object y, x\n")
12296     (write _test-input-stream "}\n")
12297     # convert
12298     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12299     # registers except esp clobbered at this point
12300     # restore ed
12301     89/<- %edx 4/r32/esp
12302     (flush _test-output-buffered-file)
12303     (flush _test-error-buffered-file)
12304 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12310     # check output
12311     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
12312     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-addr: error message")
12313     # check that stop(1) was called
12314     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
12315     # don't restore from ebp
12316     81 0/subop/add %esp 8/imm32
12317     # . epilogue
12318     5d/pop-to-ebp
12319     c3/return
12320 
12321 test-copy-object-non-equal:
12322     # . prologue
12323     55/push-ebp
12324     89/<- %ebp 4/r32/esp
12325     # setup
12326     (clear-stream _test-input-stream)
12327     (clear-stream $_test-input-buffered-file->buffer)
12328     (clear-stream _test-output-stream)
12329     (clear-stream $_test-output-buffered-file->buffer)
12330     (clear-stream _test-error-stream)
12331     (clear-stream $_test-error-buffered-file->buffer)
12332     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12333     68/push 0/imm32
12334     68/push 0/imm32
12335     89/<- %edx 4/r32/esp
12336     (tailor-exit-descriptor %edx 0x10)
12337     #
12338     (write _test-input-stream "fn foo {\n")
12339     (write _test-input-stream "  var x: (addr int)\n")
12340     (write _test-input-stream "  var y: (addr boolean)\n")
12341     (write _test-input-stream "  copy-object y, x\n")
12342     (write _test-input-stream "}\n")
12343     # convert
12344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12345     # registers except esp clobbered at this point
12346     # restore ed
12347     89/<- %edx 4/r32/esp
12348     (flush _test-output-buffered-file)
12349     (flush _test-error-buffered-file)
12350 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12356     # check output
12357     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
12358     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-equal: error message")
12359     # check that stop(1) was called
12360     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
12361     # don't restore from ebp
12362     81 0/subop/add %esp 8/imm32
12363     # . epilogue
12364     5d/pop-to-ebp
12365     c3/return
12366 
12367 test-allocate-with-no-inout:
12368     # . prologue
12369     55/push-ebp
12370     89/<- %ebp 4/r32/esp
12371     # setup
12372     (clear-stream _test-input-stream)
12373     (clear-stream $_test-input-buffered-file->buffer)
12374     (clear-stream _test-output-stream)
12375     (clear-stream $_test-output-buffered-file->buffer)
12376     (clear-stream _test-error-stream)
12377     (clear-stream $_test-error-buffered-file->buffer)
12378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12379     68/push 0/imm32
12380     68/push 0/imm32
12381     89/<- %edx 4/r32/esp
12382     (tailor-exit-descriptor %edx 0x10)
12383     #
12384     (write _test-input-stream "fn foo {\n")
12385     (write _test-input-stream "  allocate\n")
12386     (write _test-input-stream "}\n")
12387     # convert
12388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12389     # registers except esp clobbered at this point
12390     # restore ed
12391     89/<- %edx 4/r32/esp
12392     (flush _test-output-buffered-file)
12393     (flush _test-error-buffered-file)
12394 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12400     # check output
12401     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
12402     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
12403     # check that stop(1) was called
12404     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
12405     # don't restore from ebp
12406     81 0/subop/add %esp 8/imm32
12407     # . epilogue
12408     5d/pop-to-ebp
12409     c3/return
12410 
12411 test-allocate-with-too-many-inouts:
12412     # . prologue
12413     55/push-ebp
12414     89/<- %ebp 4/r32/esp
12415     # setup
12416     (clear-stream _test-input-stream)
12417     (clear-stream $_test-input-buffered-file->buffer)
12418     (clear-stream _test-output-stream)
12419     (clear-stream $_test-output-buffered-file->buffer)
12420     (clear-stream _test-error-stream)
12421     (clear-stream $_test-error-buffered-file->buffer)
12422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12423     68/push 0/imm32
12424     68/push 0/imm32
12425     89/<- %edx 4/r32/esp
12426     (tailor-exit-descriptor %edx 0x10)
12427     #
12428     (write _test-input-stream "fn foo {\n")
12429     (write _test-input-stream "  var x: (addr handle int)\n")
12430     (write _test-input-stream "  allocate x, 0\n")
12431     (write _test-input-stream "}\n")
12432     # convert
12433     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12434     # registers except esp clobbered at this point
12435     # restore ed
12436     89/<- %edx 4/r32/esp
12437     (flush _test-output-buffered-file)
12438     (flush _test-error-buffered-file)
12439 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12445     # check output
12446     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
12447     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-too-many-inouts: error message")
12448     # check that stop(1) was called
12449     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
12450     # don't restore from ebp
12451     81 0/subop/add %esp 8/imm32
12452     # . epilogue
12453     5d/pop-to-ebp
12454     c3/return
12455 
12456 test-allocate-with-output:
12457     # . prologue
12458     55/push-ebp
12459     89/<- %ebp 4/r32/esp
12460     # setup
12461     (clear-stream _test-input-stream)
12462     (clear-stream $_test-input-buffered-file->buffer)
12463     (clear-stream _test-output-stream)
12464     (clear-stream $_test-output-buffered-file->buffer)
12465     (clear-stream _test-error-stream)
12466     (clear-stream $_test-error-buffered-file->buffer)
12467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12468     68/push 0/imm32
12469     68/push 0/imm32
12470     89/<- %edx 4/r32/esp
12471     (tailor-exit-descriptor %edx 0x10)
12472     #
12473     (write _test-input-stream "fn foo {\n")
12474     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
12475     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
12476     (write _test-input-stream "  x <- allocate y\n")
12477     (write _test-input-stream "}\n")
12478     # convert
12479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12480     # registers except esp clobbered at this point
12481     # restore ed
12482     89/<- %edx 4/r32/esp
12483     (flush _test-output-buffered-file)
12484     (flush _test-error-buffered-file)
12485 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12491     # check output
12492     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
12493     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
12494     # check that stop(1) was called
12495     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
12496     # don't restore from ebp
12497     81 0/subop/add %esp 8/imm32
12498     # . epilogue
12499     5d/pop-to-ebp
12500     c3/return
12501 
12502 test-allocate-non-addr:
12503     # . prologue
12504     55/push-ebp
12505     89/<- %ebp 4/r32/esp
12506     # setup
12507     (clear-stream _test-input-stream)
12508     (clear-stream $_test-input-buffered-file->buffer)
12509     (clear-stream _test-output-stream)
12510     (clear-stream $_test-output-buffered-file->buffer)
12511     (clear-stream _test-error-stream)
12512     (clear-stream $_test-error-buffered-file->buffer)
12513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12514     68/push 0/imm32
12515     68/push 0/imm32
12516     89/<- %edx 4/r32/esp
12517     (tailor-exit-descriptor %edx 0x10)
12518     #
12519     (write _test-input-stream "fn foo {\n")
12520     (write _test-input-stream "  var y/ecx: (handle int) <- copy 0\n")
12521     (write _test-input-stream "  allocate y\n")
12522     (write _test-input-stream "}\n")
12523     # convert
12524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12525     # registers except esp clobbered at this point
12526     # restore ed
12527     89/<- %edx 4/r32/esp
12528     (flush _test-output-buffered-file)
12529     (flush _test-error-buffered-file)
12530 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12536     # check output
12537     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
12538     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
12539     # check that stop(1) was called
12540     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
12541     # don't restore from ebp
12542     81 0/subop/add %esp 8/imm32
12543     # . epilogue
12544     5d/pop-to-ebp
12545     c3/return
12546 
12547 test-allocate-non-addr-handle:
12548     # . prologue
12549     55/push-ebp
12550     89/<- %ebp 4/r32/esp
12551     # setup
12552     (clear-stream _test-input-stream)
12553     (clear-stream $_test-input-buffered-file->buffer)
12554     (clear-stream _test-output-stream)
12555     (clear-stream $_test-output-buffered-file->buffer)
12556     (clear-stream _test-error-stream)
12557     (clear-stream $_test-error-buffered-file->buffer)
12558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12559     68/push 0/imm32
12560     68/push 0/imm32
12561     89/<- %edx 4/r32/esp
12562     (tailor-exit-descriptor %edx 0x10)
12563     #
12564     (write _test-input-stream "fn foo {\n")
12565     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
12566     (write _test-input-stream "  allocate y\n")
12567     (write _test-input-stream "}\n")
12568     # convert
12569     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12570     # registers except esp clobbered at this point
12571     # restore ed
12572     89/<- %edx 4/r32/esp
12573     (flush _test-output-buffered-file)
12574     (flush _test-error-buffered-file)
12575 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12581     # check output
12582     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
12583     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr-handle: error message")
12584     # check that stop(1) was called
12585     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
12586     # don't restore from ebp
12587     81 0/subop/add %esp 8/imm32
12588     # . epilogue
12589     5d/pop-to-ebp
12590     c3/return
12591 
12592 test-allocate-deref-address:
12593     # . prologue
12594     55/push-ebp
12595     89/<- %ebp 4/r32/esp
12596     # setup
12597     (clear-stream _test-input-stream)
12598     (clear-stream $_test-input-buffered-file->buffer)
12599     (clear-stream _test-output-stream)
12600     (clear-stream $_test-output-buffered-file->buffer)
12601     #
12602     (write _test-input-stream "fn foo {\n")
12603     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
12604     (write _test-input-stream "  allocate *y\n")
12605     (write _test-input-stream "}\n")
12606     # convert
12607     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12608     (flush _test-output-buffered-file)
12609 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12615     # not bothering checking output
12616     (check-next-stream-line-equal _test-error-stream  ""  "F - test-allocate-deref-address: error message")
12617     # . epilogue
12618     5d/pop-to-ebp
12619     c3/return
12620 
12621 test-populate-with-no-inout:
12622     # . prologue
12623     55/push-ebp
12624     89/<- %ebp 4/r32/esp
12625     # setup
12626     (clear-stream _test-input-stream)
12627     (clear-stream $_test-input-buffered-file->buffer)
12628     (clear-stream _test-output-stream)
12629     (clear-stream $_test-output-buffered-file->buffer)
12630     (clear-stream _test-error-stream)
12631     (clear-stream $_test-error-buffered-file->buffer)
12632     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12633     68/push 0/imm32
12634     68/push 0/imm32
12635     89/<- %edx 4/r32/esp
12636     (tailor-exit-descriptor %edx 0x10)
12637     #
12638     (write _test-input-stream "fn foo {\n")
12639     (write _test-input-stream "  populate\n")
12640     (write _test-input-stream "}\n")
12641     # convert
12642     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12643     # registers except esp clobbered at this point
12644     # restore ed
12645     89/<- %edx 4/r32/esp
12646     (flush _test-output-buffered-file)
12647     (flush _test-error-buffered-file)
12648 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12654     # check output
12655     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
12656     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
12657     # check that stop(1) was called
12658     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
12659     # don't restore from ebp
12660     81 0/subop/add %esp 8/imm32
12661     # . epilogue
12662     5d/pop-to-ebp
12663     c3/return
12664 
12665 test-populate-with-too-many-inouts:
12666     # . prologue
12667     55/push-ebp
12668     89/<- %ebp 4/r32/esp
12669     # setup
12670     (clear-stream _test-input-stream)
12671     (clear-stream $_test-input-buffered-file->buffer)
12672     (clear-stream _test-output-stream)
12673     (clear-stream $_test-output-buffered-file->buffer)
12674     (clear-stream _test-error-stream)
12675     (clear-stream $_test-error-buffered-file->buffer)
12676     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12677     68/push 0/imm32
12678     68/push 0/imm32
12679     89/<- %edx 4/r32/esp
12680     (tailor-exit-descriptor %edx 0x10)
12681     #
12682     (write _test-input-stream "fn foo {\n")
12683     (write _test-input-stream "  var x: (addr handle int)\n")
12684     (write _test-input-stream "  populate x, 3, 0\n")
12685     (write _test-input-stream "}\n")
12686     # convert
12687     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12688     # registers except esp clobbered at this point
12689     # restore ed
12690     89/<- %edx 4/r32/esp
12691     (flush _test-output-buffered-file)
12692     (flush _test-error-buffered-file)
12693 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12699     # check output
12700     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
12701     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-too-many-inouts: error message")
12702     # check that stop(1) was called
12703     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
12704     # don't restore from ebp
12705     81 0/subop/add %esp 8/imm32
12706     # . epilogue
12707     5d/pop-to-ebp
12708     c3/return
12709 
12710 test-populate-with-output:
12711     # . prologue
12712     55/push-ebp
12713     89/<- %ebp 4/r32/esp
12714     # setup
12715     (clear-stream _test-input-stream)
12716     (clear-stream $_test-input-buffered-file->buffer)
12717     (clear-stream _test-output-stream)
12718     (clear-stream $_test-output-buffered-file->buffer)
12719     (clear-stream _test-error-stream)
12720     (clear-stream $_test-error-buffered-file->buffer)
12721     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12722     68/push 0/imm32
12723     68/push 0/imm32
12724     89/<- %edx 4/r32/esp
12725     (tailor-exit-descriptor %edx 0x10)
12726     #
12727     (write _test-input-stream "fn foo {\n")
12728     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
12729     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
12730     (write _test-input-stream "  x <- populate y\n")
12731     (write _test-input-stream "}\n")
12732     # convert
12733     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12734     # registers except esp clobbered at this point
12735     # restore ed
12736     89/<- %edx 4/r32/esp
12737     (flush _test-output-buffered-file)
12738     (flush _test-error-buffered-file)
12739 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12745     # check output
12746     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
12747     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
12748     # check that stop(1) was called
12749     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
12750     # don't restore from ebp
12751     81 0/subop/add %esp 8/imm32
12752     # . epilogue
12753     5d/pop-to-ebp
12754     c3/return
12755 
12756 test-populate-non-addr:
12757     # . prologue
12758     55/push-ebp
12759     89/<- %ebp 4/r32/esp
12760     # setup
12761     (clear-stream _test-input-stream)
12762     (clear-stream $_test-input-buffered-file->buffer)
12763     (clear-stream _test-output-stream)
12764     (clear-stream $_test-output-buffered-file->buffer)
12765     (clear-stream _test-error-stream)
12766     (clear-stream $_test-error-buffered-file->buffer)
12767     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12768     68/push 0/imm32
12769     68/push 0/imm32
12770     89/<- %edx 4/r32/esp
12771     (tailor-exit-descriptor %edx 0x10)
12772     #
12773     (write _test-input-stream "fn foo {\n")
12774     (write _test-input-stream "  var y/ecx: (handle int) <- copy 0\n")
12775     (write _test-input-stream "  populate y, 3\n")
12776     (write _test-input-stream "}\n")
12777     # convert
12778     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12779     # registers except esp clobbered at this point
12780     # restore ed
12781     89/<- %edx 4/r32/esp
12782     (flush _test-output-buffered-file)
12783     (flush _test-error-buffered-file)
12784 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12790     # check output
12791     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
12792     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
12793     # check that stop(1) was called
12794     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
12795     # don't restore from ebp
12796     81 0/subop/add %esp 8/imm32
12797     # . epilogue
12798     5d/pop-to-ebp
12799     c3/return
12800 
12801 test-populate-non-addr-handle:
12802     # . prologue
12803     55/push-ebp
12804     89/<- %ebp 4/r32/esp
12805     # setup
12806     (clear-stream _test-input-stream)
12807     (clear-stream $_test-input-buffered-file->buffer)
12808     (clear-stream _test-output-stream)
12809     (clear-stream $_test-output-buffered-file->buffer)
12810     (clear-stream _test-error-stream)
12811     (clear-stream $_test-error-buffered-file->buffer)
12812     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12813     68/push 0/imm32
12814     68/push 0/imm32
12815     89/<- %edx 4/r32/esp
12816     (tailor-exit-descriptor %edx 0x10)
12817     #
12818     (write _test-input-stream "fn foo {\n")
12819     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
12820     (write _test-input-stream "  populate y, 3\n")
12821     (write _test-input-stream "}\n")
12822     # convert
12823     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12824     # registers except esp clobbered at this point
12825     # restore ed
12826     89/<- %edx 4/r32/esp
12827     (flush _test-output-buffered-file)
12828     (flush _test-error-buffered-file)
12829 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12835     # check output
12836     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
12837     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
12838     # check that stop(1) was called
12839     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
12840     # don't restore from ebp
12841     81 0/subop/add %esp 8/imm32
12842     # . epilogue
12843     5d/pop-to-ebp
12844     c3/return
12845 
12846 test-populate-non-addr-handle-array:
12847     # . prologue
12848     55/push-ebp
12849     89/<- %ebp 4/r32/esp
12850     # setup
12851     (clear-stream _test-input-stream)
12852     (clear-stream $_test-input-buffered-file->buffer)
12853     (clear-stream _test-output-stream)
12854     (clear-stream $_test-output-buffered-file->buffer)
12855     (clear-stream _test-error-stream)
12856     (clear-stream $_test-error-buffered-file->buffer)
12857     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12858     68/push 0/imm32
12859     68/push 0/imm32
12860     89/<- %edx 4/r32/esp
12861     (tailor-exit-descriptor %edx 0x10)
12862     #
12863     (write _test-input-stream "fn foo {\n")
12864     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
12865     (write _test-input-stream "  populate y, 3\n")
12866     (write _test-input-stream "}\n")
12867     # convert
12868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12869     # registers except esp clobbered at this point
12870     # restore ed
12871     89/<- %edx 4/r32/esp
12872     (flush _test-output-buffered-file)
12873     (flush _test-error-buffered-file)
12874 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12880     # check output
12881     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
12882     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle-array: error message")
12883     # check that stop(1) was called
12884     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
12885     # don't restore from ebp
12886     81 0/subop/add %esp 8/imm32
12887     # . epilogue
12888     5d/pop-to-ebp
12889     c3/return
12890 
12891 test-populate-deref-address:
12892     # . prologue
12893     55/push-ebp
12894     89/<- %ebp 4/r32/esp
12895     # setup
12896     (clear-stream _test-input-stream)
12897     (clear-stream $_test-input-buffered-file->buffer)
12898     (clear-stream _test-output-stream)
12899     (clear-stream $_test-output-buffered-file->buffer)
12900     #
12901     (write _test-input-stream "fn foo {\n")
12902     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
12903     (write _test-input-stream "  populate *y, 3\n")
12904     (write _test-input-stream "}\n")
12905     # convert
12906     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12907     (flush _test-output-buffered-file)
12908 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12914     # not bothering checking output
12915     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-deref-address: error message")
12916     # . epilogue
12917     5d/pop-to-ebp
12918     c3/return
12919 
12920 test-populate-stream-with-no-inout:
12921     # . prologue
12922     55/push-ebp
12923     89/<- %ebp 4/r32/esp
12924     # setup
12925     (clear-stream _test-input-stream)
12926     (clear-stream $_test-input-buffered-file->buffer)
12927     (clear-stream _test-output-stream)
12928     (clear-stream $_test-output-buffered-file->buffer)
12929     (clear-stream _test-error-stream)
12930     (clear-stream $_test-error-buffered-file->buffer)
12931     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12932     68/push 0/imm32
12933     68/push 0/imm32
12934     89/<- %edx 4/r32/esp
12935     (tailor-exit-descriptor %edx 0x10)
12936     #
12937     (write _test-input-stream "fn foo {\n")
12938     (write _test-input-stream "  populate-stream\n")
12939     (write _test-input-stream "}\n")
12940     # convert
12941     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12942     # registers except esp clobbered at this point
12943     # restore ed
12944     89/<- %edx 4/r32/esp
12945     (flush _test-output-buffered-file)
12946     (flush _test-error-buffered-file)
12947 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12953     # check output
12954     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
12955     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
12956     # check that stop(1) was called
12957     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
12958     # don't restore from ebp
12959     81 0/subop/add %esp 8/imm32
12960     # . epilogue
12961     5d/pop-to-ebp
12962     c3/return
12963 
12964 test-populate-stream-with-too-many-inouts:
12965     # . prologue
12966     55/push-ebp
12967     89/<- %ebp 4/r32/esp
12968     # setup
12969     (clear-stream _test-input-stream)
12970     (clear-stream $_test-input-buffered-file->buffer)
12971     (clear-stream _test-output-stream)
12972     (clear-stream $_test-output-buffered-file->buffer)
12973     (clear-stream _test-error-stream)
12974     (clear-stream $_test-error-buffered-file->buffer)
12975     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12976     68/push 0/imm32
12977     68/push 0/imm32
12978     89/<- %edx 4/r32/esp
12979     (tailor-exit-descriptor %edx 0x10)
12980     #
12981     (write _test-input-stream "fn foo {\n")
12982     (write _test-input-stream "  var x: (addr handle int)\n")
12983     (write _test-input-stream "  populate-stream x, 3, 0\n")
12984     (write _test-input-stream "}\n")
12985     # convert
12986     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12987     # registers except esp clobbered at this point
12988     # restore ed
12989     89/<- %edx 4/r32/esp
12990     (flush _test-output-buffered-file)
12991     (flush _test-error-buffered-file)
12992 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
12998     # check output
12999     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
13000     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-too-many-inouts: error message")
13001     # check that stop(1) was called
13002     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
13003     # don't restore from ebp
13004     81 0/subop/add %esp 8/imm32
13005     # . epilogue
13006     5d/pop-to-ebp
13007     c3/return
13008 
13009 test-populate-stream-with-output:
13010     # . prologue
13011     55/push-ebp
13012     89/<- %ebp 4/r32/esp
13013     # setup
13014     (clear-stream _test-input-stream)
13015     (clear-stream $_test-input-buffered-file->buffer)
13016     (clear-stream _test-output-stream)
13017     (clear-stream $_test-output-buffered-file->buffer)
13018     (clear-stream _test-error-stream)
13019     (clear-stream $_test-error-buffered-file->buffer)
13020     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13021     68/push 0/imm32
13022     68/push 0/imm32
13023     89/<- %edx 4/r32/esp
13024     (tailor-exit-descriptor %edx 0x10)
13025     #
13026     (write _test-input-stream "fn foo {\n")
13027     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13028     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13029     (write _test-input-stream "  x <- populate-stream y\n")
13030     (write _test-input-stream "}\n")
13031     # convert
13032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13033     # registers except esp clobbered at this point
13034     # restore ed
13035     89/<- %edx 4/r32/esp
13036     (flush _test-output-buffered-file)
13037     (flush _test-error-buffered-file)
13038 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
13044     # check output
13045     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
13046     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must not have any outputs"  "F - test-populate-stream-with-output: error message")
13047     # check that stop(1) was called
13048     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
13049     # don't restore from ebp
13050     81 0/subop/add %esp 8/imm32
13051     # . epilogue
13052     5d/pop-to-ebp
13053     c3/return
13054 
13055 test-populate-stream-non-addr:
13056     # . prologue
13057     55/push-ebp
13058     89/<- %ebp 4/r32/esp
13059     # setup
13060     (clear-stream _test-input-stream)
13061     (clear-stream $_test-input-buffered-file->buffer)
13062     (clear-stream _test-output-stream)
13063     (clear-stream $_test-output-buffered-file->buffer)
13064     (clear-stream _test-error-stream)
13065     (clear-stream $_test-error-buffered-file->buffer)
13066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13067     68/push 0/imm32
13068     68/push 0/imm32
13069     89/<- %edx 4/r32/esp
13070     (tailor-exit-descriptor %edx 0x10)
13071     #
13072     (write _test-input-stream "fn foo {\n")
13073     (write _test-input-stream "  var y/ecx: (handle int) <- copy 0\n")
13074     (write _test-input-stream "  populate-stream y, 3\n")
13075     (write _test-input-stream "}\n")
13076     # convert
13077     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13078     # registers except esp clobbered at this point
13079     # restore ed
13080     89/<- %edx 4/r32/esp
13081     (flush _test-output-buffered-file)
13082     (flush _test-error-buffered-file)
13083 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
13089     # check output
13090     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
13091     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
13092     # check that stop(1) was called
13093     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
13094     # don't restore from ebp
13095     81 0/subop/add %esp 8/imm32
13096     # . epilogue
13097     5d/pop-to-ebp
13098     c3/return
13099 
13100 test-populate-stream-non-addr-handle:
13101     # . prologue
13102     55/push-ebp
13103     89/<- %ebp 4/r32/esp
13104     # setup
13105     (clear-stream _test-input-stream)
13106     (clear-stream $_test-input-buffered-file->buffer)
13107     (clear-stream _test-output-stream)
13108     (clear-stream $_test-output-buffered-file->buffer)
13109     (clear-stream _test-error-stream)
13110     (clear-stream $_test-error-buffered-file->buffer)
13111     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13112     68/push 0/imm32
13113     68/push 0/imm32
13114     89/<- %edx 4/r32/esp
13115     (tailor-exit-descriptor %edx 0x10)
13116     #
13117     (write _test-input-stream "fn foo {\n")
13118     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13119     (write _test-input-stream "  populate-stream y, 3\n")
13120     (write _test-input-stream "}\n")
13121     # convert
13122     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13123     # registers except esp clobbered at this point
13124     # restore ed
13125     89/<- %edx 4/r32/esp
13126     (flush _test-output-buffered-file)
13127     (flush _test-error-buffered-file)
13128 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
13134     # check output
13135     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
13136     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
13137     # check that stop(1) was called
13138     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
13139     # don't restore from ebp
13140     81 0/subop/add %esp 8/imm32
13141     # . epilogue
13142     5d/pop-to-ebp
13143     c3/return
13144 
13145 test-populate-stream-non-addr-handle-stream:
13146     # . prologue
13147     55/push-ebp
13148     89/<- %ebp 4/r32/esp
13149     # setup
13150     (clear-stream _test-input-stream)
13151     (clear-stream $_test-input-buffered-file->buffer)
13152     (clear-stream _test-output-stream)
13153     (clear-stream $_test-output-buffered-file->buffer)
13154     (clear-stream _test-error-stream)
13155     (clear-stream $_test-error-buffered-file->buffer)
13156     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13157     68/push 0/imm32
13158     68/push 0/imm32
13159     89/<- %edx 4/r32/esp
13160     (tailor-exit-descriptor %edx 0x10)
13161     #
13162     (write _test-input-stream "fn foo {\n")
13163     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13164     (write _test-input-stream "  populate-stream y, 3\n")
13165     (write _test-input-stream "}\n")
13166     # convert
13167     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13168     # registers except esp clobbered at this point
13169     # restore ed
13170     89/<- %edx 4/r32/esp
13171     (flush _test-output-buffered-file)
13172     (flush _test-error-buffered-file)
13173 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
13179     # check output
13180     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
13181     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle-stream: error message")
13182     # check that stop(1) was called
13183     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
13184     # don't restore from ebp
13185     81 0/subop/add %esp 8/imm32
13186     # . epilogue
13187     5d/pop-to-ebp
13188     c3/return
13189 
13190 test-populate-stream-deref-address:
13191     # . prologue
13192     55/push-ebp
13193     89/<- %ebp 4/r32/esp
13194     # setup
13195     (clear-stream _test-input-stream)
13196     (clear-stream $_test-input-buffered-file->buffer)
13197     (clear-stream _test-output-stream)
13198     (clear-stream $_test-output-buffered-file->buffer)
13199     #
13200     (write _test-input-stream "fn foo {\n")
13201     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
13202     (write _test-input-stream "  populate-stream *y, 3\n")
13203     (write _test-input-stream "}\n")
13204     # convert
13205     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13206     (flush _test-output-buffered-file)
13207 +--  6 lines: #?     # dump _test-error-stream -------------------------------------------------------------------------------------------------------------------------------------------------------------------
13213     # not bothering checking output
13214     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-stream-deref-address: error message")
13215     # . epilogue
13216     5d/pop-to-ebp
13217     c3/return
13218 
13219 #######################################################
13220 # Parsing
13221 #######################################################
13222 
13223 == data
13224 
13225 # Global state added to each var record when parsing a function
13226 Next-block-index:  # (addr int)
13227     1/imm32
13228 
13229 Curr-block-depth:  # (addr int)
13230     1/imm32
13231 
13232 == code
13233 
13234 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
13235     # pseudocode
13236     #   var curr-function: (addr handle function) = Program->functions
13237     #   var curr-signature: (addr handle function) = Program->signatures
13238     #   var curr-type: (addr handle typeinfo) = Program->types
13239     #   var line: (stream byte 512)
13240     #   var word-slice: slice
13241     #   while true                                  # line loop
13242     #     clear-stream(line)
13243     #     read-line-buffered(in, line)
13244     #     if (line->write == 0) break               # end of file
13245     #     word-slice = next-mu-token(line)
13246     #     if slice-empty?(word-slice)               # end of line
13247     #       continue
13248     #     else if slice-starts-with?(word-slice, "#")  # comment
13249     #       continue                                # end of line
13250     #     else if slice-equal?(word-slice, "fn")
13251     #       var new-function: (handle function) = allocate(function)
13252     #       var vars: (stack live-var 256)
13253     #       populate-mu-function-header(line, new-function, vars)
13254     #       populate-mu-function-body(in, new-function, vars)
13255     #       assert(vars->top == 0)
13256     #       *curr-function = new-function
13257     #       curr-function = &new-function->next
13258     #     else if slice-equal?(word-slice, "sig")
13259     #       var new-function: (handle function) = allocate(function)
13260     #       populate-mu-function-signature(line, new-function)
13261     #       *curr-signature = new-function
13262     #       curr-signature = &new-function->next
13263     #     else if slice-equal?(word-slice, "type")
13264     #       word-slice = next-mu-token(line)
13265     #       type-id = pos-or-insert-slice(Type-id, word-slice)
13266     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
13267     #       assert(next-word(line) == "{")
13268     #       populate-mu-type(in, new-type)
13269     #     else
13270     #       abort()
13271     #
13272     # . prologue
13273     55/push-ebp
13274     89/<- %ebp 4/r32/esp
13275     # var curr-signature: (addr handle function) at *(ebp-4)
13276     68/push _Program-signatures/imm32
13277     # . save registers
13278     50/push-eax
13279     51/push-ecx
13280     52/push-edx
13281     53/push-ebx
13282     56/push-esi
13283     57/push-edi
13284     # var line/ecx: (stream byte 512)
13285     81 5/subop/subtract %esp 0x200/imm32
13286     68/push 0x200/imm32/size
13287     68/push 0/imm32/read
13288     68/push 0/imm32/write
13289     89/<- %ecx 4/r32/esp
13290     # var word-slice/edx: slice
13291     68/push 0/imm32/end
13292     68/push 0/imm32/start
13293     89/<- %edx 4/r32/esp
13294     # var curr-function/edi: (addr handle function)
13295     bf/copy-to-edi _Program-functions/imm32
13296     # var vars/ebx: (stack live-var 256)
13297     81 5/subop/subtract %esp 0xc00/imm32
13298     68/push 0xc00/imm32/size
13299     68/push 0/imm32/top
13300     89/<- %ebx 4/r32/esp
13301     {
13302 $parse-mu:line-loop:
13303       (clear-stream %ecx)
13304       (read-line-buffered *(ebp+8) %ecx)
13305       # if (line->write == 0) break
13306       81 7/subop/compare *ecx 0/imm32
13307       0f 84/jump-if-= break/disp32
13308 +--  6 lines: #?       # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13314       (next-mu-token %ecx %edx)
13315       # if slice-empty?(word-slice) continue
13316       (slice-empty? %edx)  # => eax
13317       3d/compare-eax-and 0/imm32/false
13318       0f 85/jump-if-!= loop/disp32
13319       # if (*word-slice->start == "#") continue
13320       # . eax = *word-slice->start
13321       8b/-> *edx 0/r32/eax
13322       8a/copy-byte *eax 0/r32/AL
13323       81 4/subop/and %eax 0xff/imm32
13324       # . if (eax == '#') continue
13325       3d/compare-eax-and 0x23/imm32/hash
13326       0f 84/jump-if-= loop/disp32
13327       # if (slice-equal?(word-slice, "fn")) parse a function
13328       {
13329 $parse-mu:fn:
13330         (slice-equal? %edx "fn")  # => eax
13331         3d/compare-eax-and 0/imm32/false
13332         0f 84/jump-if-= break/disp32
13333         # var new-function/esi: (handle function)
13334         68/push 0/imm32
13335         68/push 0/imm32
13336         89/<- %esi 4/r32/esp
13337         # populate-mu-function(line, in, vars, new-function)
13338         (allocate Heap *Function-size %esi)
13339         # var new-function-addr/eax: (addr function)
13340         (lookup *esi *(esi+4))  # => eax
13341         # initialize vars
13342         (clear-stack %ebx)
13343         #
13344         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
13345         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
13346         # *curr-function = new-function
13347         8b/-> *esi 0/r32/eax
13348         89/<- *edi 0/r32/eax
13349         8b/-> *(esi+4) 0/r32/eax
13350         89/<- *(edi+4) 0/r32/eax
13351         # curr-function = &new-function->next
13352         # . var tmp/eax: (addr function) = lookup(new-function)
13353         (lookup *esi *(esi+4))  # => eax
13354         # . curr-function = &tmp->next
13355         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
13356         # reclaim new-function
13357         81 0/subop/add %esp 8/imm32
13358         #
13359         e9/jump $parse-mu:line-loop/disp32
13360       }
13361       # if (slice-equal?(word-slice, "sig")) parse a function signature
13362       # Function signatures are for providing types to SubX functions.
13363       {
13364 $parse-mu:sig:
13365         (slice-equal? %edx "sig")  # => eax
13366         3d/compare-eax-and 0/imm32/false
13367         0f 84/jump-if-= break/disp32
13368         # edi = curr-function
13369         57/push-edi
13370         8b/-> *(ebp-4) 7/r32/edi
13371         # var new-function/esi: (handle function)
13372         68/push 0/imm32
13373         68/push 0/imm32
13374         89/<- %esi 4/r32/esp
13375         # populate-mu-function(line, in, vars, new-function)
13376         (allocate Heap *Function-size %esi)
13377         # var new-function-addr/eax: (addr function)
13378         (lookup *esi *(esi+4))  # => eax
13379         #
13380         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
13381         # *curr-signature = new-function
13382         8b/-> *esi 0/r32/eax
13383         89/<- *edi 0/r32/eax
13384         8b/-> *(esi+4) 0/r32/eax
13385         89/<- *(edi+4) 0/r32/eax
13386         # curr-signature = &new-function->next
13387         # . var tmp/eax: (addr function) = lookup(new-function)
13388         (lookup *esi *(esi+4))  # => eax
13389         # . curr-function = &tmp->next
13390         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
13391         # reclaim new-function
13392         81 0/subop/add %esp 8/imm32
13393         # save curr-function
13394         89/<- *(ebp-4) 7/r32/edi
13395         # restore edi
13396         5f/pop-to-edi
13397         #
13398         e9/jump $parse-mu:line-loop/disp32
13399       }
13400       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
13401       {
13402 $parse-mu:type:
13403         (slice-equal? %edx "type")  # => eax
13404         3d/compare-eax-and 0/imm32
13405         0f 84/jump-if-= break/disp32
13406         (next-mu-token %ecx %edx)
13407         # var type-id/eax: int
13408         (pos-or-insert-slice Type-id %edx)  # => eax
13409         # spill
13410         51/push-ecx
13411         # var new-type/ecx: (handle typeinfo)
13412         68/push 0/imm32
13413         68/push 0/imm32
13414         89/<- %ecx 4/r32/esp
13415         (find-or-create-typeinfo %eax %ecx)
13416         #
13417         (lookup *ecx *(ecx+4))  # => eax
13418         # TODO: ensure that 'line' has nothing else but '{'
13419 #? (dump-typeinfos "=== aaa\n")
13420         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
13421 #? (dump-typeinfos "=== zzz\n")
13422         # reclaim new-type
13423         81 0/subop/add %esp 8/imm32
13424         # restore
13425         59/pop-to-ecx
13426         e9/jump $parse-mu:line-loop/disp32
13427       }
13428       # otherwise abort
13429       e9/jump $parse-mu:error1/disp32
13430     } # end line loop
13431 $parse-mu:end:
13432     # . reclaim locals
13433     81 0/subop/add %esp 0x20c/imm32  # line
13434     81 0/subop/add %esp 0xc08/imm32  # vars
13435     81 0/subop/add %esp 8/imm32
13436     # . restore registers
13437     5f/pop-to-edi
13438     5e/pop-to-esi
13439     5b/pop-to-ebx
13440     5a/pop-to-edx
13441     59/pop-to-ecx
13442     58/pop-to-eax
13443     # . reclaim local
13444     81 0/subop/add %esp 4/imm32
13445     # . epilogue
13446     89/<- %esp 5/r32/ebp
13447     5d/pop-to-ebp
13448     c3/return
13449 
13450 $parse-mu:error1:
13451     # error("unexpected top-level command: " word-slice "\n")
13452     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
13453     (write-slice-buffered *(ebp+0xc) %edx)
13454     (write-buffered *(ebp+0xc) "\n")
13455     (flush *(ebp+0xc))
13456     (stop *(ebp+0x10) 1)
13457     # never gets here
13458 
13459 $parse-mu:error2:
13460     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
13461     (write-int32-hex-buffered *(ebp+0xc) *ebx)
13462     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
13463     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
13464     (write-buffered *(ebp+0xc) "'\n")
13465     (flush *(ebp+0xc))
13466     (stop *(ebp+0x10) 1)
13467     # never gets here
13468 
13469 # scenarios considered:
13470 # ✗ fn foo  # no block
13471 # ✓ fn foo {
13472 # ✗ fn foo { {
13473 # ✗ fn foo { }
13474 # ✗ fn foo { } {
13475 # ✗ fn foo x {
13476 # ✗ fn foo x: {
13477 # ✓ fn foo x: int {
13478 # ✓ fn foo x: int {
13479 # ✓ fn foo x: int -> _/eax: int {
13480 # TODO:
13481 #   disallow outputs of type `(... addr ...)`
13482 #   disallow inputs of type `(... addr ... addr ...)`
13483 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)
13484     # pseudocode:
13485     #   var word-slice: slice
13486     #   next-mu-token(first-line, word-slice)
13487     #   if slice-empty?(word-slice) abort
13488     #   assert(word-slice not in '{' '}' '->')
13489     #   out->name = slice-to-string(word-slice)
13490     #   ## inouts
13491     #   while true
13492     #     word-slice = next-mu-token(first-line)
13493     #     if slice-empty?(word-slice) abort
13494     #     if (word-slice == '{') goto done
13495     #     if (word-slice == '->') break
13496     #     assert(word-slice != '}')
13497     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
13498     #     assert(v->register == null)
13499     #     # v->block-depth is implicitly 0
13500     #     out->inouts = append(v, out->inouts)
13501     #     push(vars, {v, false})
13502     #   ## outputs
13503     #   while true
13504     #     word-slice = next-mu-token(first-line)
13505     #     if slice-empty?(word-slice) abort
13506     #     if (word-slice == '{') break
13507     #     assert(word-slice not in '}' '->')
13508     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
13509     #     assert(v->register != null)
13510     #     assert(v->name == "_")
13511     #     out->outputs = append(v, out->outputs)
13512     #   done:
13513     #
13514     # . prologue
13515     55/push-ebp
13516     89/<- %ebp 4/r32/esp
13517     # . save registers
13518     50/push-eax
13519     51/push-ecx
13520     52/push-edx
13521     53/push-ebx
13522     57/push-edi
13523     # edi = out
13524     8b/-> *(ebp+0xc) 7/r32/edi
13525     # var word-slice/ecx: slice
13526     68/push 0/imm32/end
13527     68/push 0/imm32/start
13528     89/<- %ecx 4/r32/esp
13529     # var v/ebx: (handle var)
13530     68/push 0/imm32
13531     68/push 0/imm32
13532     89/<- %ebx 4/r32/esp
13533     # read function name
13534     (next-mu-token *(ebp+8) %ecx)
13535     # error checking
13536     # if slice-empty?(word-slice) abort
13537     (slice-empty? %ecx)  # => eax
13538     3d/compare-eax-and 0/imm32/false
13539     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13540     # if (word-slice == '{') abort
13541     (slice-equal? %ecx "{")   # => eax
13542     3d/compare-eax-and 0/imm32/false
13543     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13544     # if (word-slice == '->') abort
13545     (slice-equal? %ecx "->")   # => eax
13546     3d/compare-eax-and 0/imm32/false
13547     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13548     # if (word-slice == '}') abort
13549     (slice-equal? %ecx "}")   # => eax
13550     3d/compare-eax-and 0/imm32/false
13551     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13552     # save function name
13553     (slice-to-string Heap %ecx %edi)  # Function-name
13554     # save function inouts
13555     {
13556 $populate-mu-function-header:check-for-inout:
13557       (next-mu-token *(ebp+8) %ecx)
13558       # if slice-empty?(word-slice) abort
13559       (slice-empty? %ecx)  # => eax
13560       3d/compare-eax-and 0/imm32/false
13561       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13562       # if (word-slice == '{') goto done
13563       (slice-equal? %ecx "{")   # => eax
13564       3d/compare-eax-and 0/imm32/false
13565       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
13566       # if (word-slice == '->') break
13567       (slice-equal? %ecx "->")   # => eax
13568       3d/compare-eax-and 0/imm32/false
13569       0f 85/jump-if-!= break/disp32
13570       # if (word-slice == '}') abort
13571       (slice-equal? %ecx "}")   # => eax
13572       3d/compare-eax-and 0/imm32/false
13573       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13574       # v = parse-var-with-type(word-slice, first-line)
13575       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
13576       # assert(v->register == null)
13577       # . eax: (addr var) = lookup(v)
13578       (lookup *ebx *(ebx+4))  # => eax
13579       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
13580       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
13581       # v->block-depth is implicitly 0
13582       #
13583       # out->inouts = append(v, out->inouts)
13584       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
13585       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
13586       # push(vars, {v, false})
13587       (push *(ebp+0x10) *ebx)
13588       (push *(ebp+0x10) *(ebx+4))
13589       (push *(ebp+0x10) 0)  # false
13590       #
13591       e9/jump loop/disp32
13592     }
13593     # save function outputs
13594     {
13595 $populate-mu-function-header:check-for-out:
13596       (next-mu-token *(ebp+8) %ecx)
13597       # if slice-empty?(word-slice) abort
13598       (slice-empty? %ecx)  # => eax
13599       3d/compare-eax-and 0/imm32/false
13600       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13601       # if (word-slice == '{') break
13602       (slice-equal? %ecx "{")   # => eax
13603       3d/compare-eax-and 0/imm32/false
13604       0f 85/jump-if-!= break/disp32
13605       # if (word-slice == '->') abort
13606       (slice-equal? %ecx "->")   # => eax
13607       3d/compare-eax-and 0/imm32/false
13608       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13609       # if (word-slice == '}') abort
13610       (slice-equal? %ecx "}")   # => eax
13611       3d/compare-eax-and 0/imm32/false
13612       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13613       # v = parse-var-with-type(word-slice, first-line)
13614       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
13615       # assert(var->register != null)
13616       # . eax: (addr var) = lookup(v)
13617       (lookup *ebx *(ebx+4))  # => eax
13618       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
13619       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
13620       # assert(var->name == "_")
13621       (lookup *eax *(eax+4))  # Var-name Var-name => eax
13622       (string-equal? %eax "_")  # => eax
13623       3d/compare-eax-and 0/imm32/false
13624       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
13625       # out->outputs = append(v, out->outputs)
13626       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
13627       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
13628       #
13629       e9/jump loop/disp32
13630     }
13631 $populate-mu-function-header:done:
13632     (check-no-tokens-left *(ebp+8))
13633 $populate-mu-function-header:end:
13634     # . reclaim locals
13635     81 0/subop/add %esp 0x10/imm32
13636     # . restore registers
13637     5f/pop-to-edi
13638     5b/pop-to-ebx
13639     5a/pop-to-edx
13640     59/pop-to-ecx
13641     58/pop-to-eax
13642     # . epilogue
13643     89/<- %esp 5/r32/ebp
13644     5d/pop-to-ebp
13645     c3/return
13646 
13647 $populate-mu-function-header:error1:
13648     # error("function header not in form 'fn <name> {'")
13649     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
13650     (flush *(ebp+0x14))
13651     (rewind-stream *(ebp+8))
13652     (write-stream-data *(ebp+0x14) *(ebp+8))
13653     (write-buffered *(ebp+0x14) "'\n")
13654     (flush *(ebp+0x14))
13655     (stop *(ebp+0x18) 1)
13656     # never gets here
13657 
13658 $populate-mu-function-header:error2:
13659     # error("fn " fn ": function inout '" var "' cannot be in a register")
13660     (write-buffered *(ebp+0x14) "fn ")
13661     50/push-eax
13662     (lookup *edi *(edi+4))  # Function-name Function-name => eax
13663     (write-buffered *(ebp+0x14) %eax)
13664     58/pop-to-eax
13665     (write-buffered *(ebp+0x14) ": function inout '")
13666     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13667     (write-buffered *(ebp+0x14) %eax)
13668     (write-buffered *(ebp+0x14) "' cannot be in a register")
13669     (flush *(ebp+0x14))
13670     (stop *(ebp+0x18) 1)
13671     # never gets here
13672 
13673 $populate-mu-function-header:error3:
13674     # error("fn " fn ": function output '" var "' must be in a register")
13675     (write-buffered *(ebp+0x14) "fn ")
13676     50/push-eax
13677     (lookup *edi *(edi+4))  # Function-name Function-name => eax
13678     (write-buffered *(ebp+0x14) %eax)
13679     58/pop-to-eax
13680     (write-buffered *(ebp+0x14) ": function output '")
13681     (lookup *ebx *(ebx+4))  # => eax
13682     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13683     (write-buffered *(ebp+0x14) %eax)
13684     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
13685     (rewind-stream *(ebp+8))
13686     (write-stream-data *(ebp+0x14) *(ebp+8))
13687     (write-buffered *(ebp+0x14) "'\n")
13688     (flush *(ebp+0x14))
13689     (stop *(ebp+0x18) 1)
13690     # never gets here
13691 
13692 $populate-mu-function-header:error4:
13693     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
13694     (write-buffered *(ebp+0x14) "fn ")
13695     50/push-eax
13696     (lookup *edi *(edi+4))  # Function-name Function-name => eax
13697     (write-buffered *(ebp+0x14) %eax)
13698     58/pop-to-eax
13699     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
13700     (lookup *ebx *(ebx+4))  # => eax
13701     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13702     (write-buffered *(ebp+0x14) %eax)
13703     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
13704     (flush *(ebp+0x14))
13705     (stop *(ebp+0x18) 1)
13706     # never gets here
13707 
13708 # scenarios considered:
13709 # ✓ fn foo
13710 # ✗ fn foo {
13711 # ✓ fn foo x
13712 # ✓ fn foo x: int
13713 # ✓ fn foo x: int -> _/eax: int
13714 # TODO:
13715 #   disallow outputs of type `(... addr ...)`
13716 #   disallow inputs of type `(... addr ... addr ...)`
13717 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13718     # pseudocode:
13719     #   var word-slice: slice
13720     #   next-mu-token(first-line, word-slice)
13721     #   assert(word-slice not in '{' '}' '->')
13722     #   out->name = slice-to-string(word-slice)
13723     #   ## inouts
13724     #   while true
13725     #     word-slice = next-mu-token(first-line)
13726     #     if slice-empty?(word-slice) break
13727     #     if (word-slice == '->') break
13728     #     assert(word-slice not in '{' '}')
13729     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
13730     #     assert(v->register == null)
13731     #     # v->block-depth is implicitly 0
13732     #     out->inouts = append(v, out->inouts)
13733     #   ## outputs
13734     #   while true
13735     #     word-slice = next-mu-token(first-line)
13736     #     if slice-empty?(word-slice) break
13737     #     assert(word-slice not in '{' '}' '->')
13738     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
13739     #     assert(v->register != null)
13740     #     out->outputs = append(v, out->outputs)
13741     #
13742     # . prologue
13743     55/push-ebp
13744     89/<- %ebp 4/r32/esp
13745     # . save registers
13746     50/push-eax
13747     51/push-ecx
13748     52/push-edx
13749     53/push-ebx
13750     57/push-edi
13751     # edi = out
13752     8b/-> *(ebp+0xc) 7/r32/edi
13753     # var word-slice/ecx: slice
13754     68/push 0/imm32/end
13755     68/push 0/imm32/start
13756     89/<- %ecx 4/r32/esp
13757     # var v/ebx: (handle var)
13758     68/push 0/imm32
13759     68/push 0/imm32
13760     89/<- %ebx 4/r32/esp
13761     # read function name
13762     (next-mu-token *(ebp+8) %ecx)
13763     # error checking
13764     # if (word-slice == '{') abort
13765     (slice-equal? %ecx "{")   # => eax
13766     3d/compare-eax-and 0/imm32/false
13767     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13768     # if (word-slice == '->') abort
13769     (slice-equal? %ecx "->")   # => eax
13770     3d/compare-eax-and 0/imm32/false
13771     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13772     # if (word-slice == '}') abort
13773     (slice-equal? %ecx "}")   # => eax
13774     3d/compare-eax-and 0/imm32/false
13775     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13776     # save function name
13777     (slice-to-string Heap %ecx %edi)  # Function-name
13778     # save function inouts
13779     {
13780 $populate-mu-function-signature:check-for-inout:
13781       (next-mu-token *(ebp+8) %ecx)
13782       (slice-empty? %ecx)  # => eax
13783       3d/compare-eax-and 0/imm32/false
13784       0f 85/jump-if-!= break/disp32
13785       # if (word-slice == '->') break
13786       (slice-equal? %ecx "->")   # => eax
13787       3d/compare-eax-and 0/imm32/false
13788       0f 85/jump-if-!= break/disp32
13789       # if (word-slice == '{') abort
13790       (slice-equal? %ecx "{")   # => eax
13791       3d/compare-eax-and 0/imm32/false
13792       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13793       # if (word-slice == '}') abort
13794       (slice-equal? %ecx "}")   # => eax
13795       3d/compare-eax-and 0/imm32/false
13796       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13797       # v = parse-var-with-type(word-slice, first-line)
13798       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
13799       # assert(v->register == null)
13800       # . eax: (addr var) = lookup(v)
13801       (lookup *ebx *(ebx+4))  # => eax
13802       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
13803       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
13804       # v->block-depth is implicitly 0
13805       #
13806       # out->inouts = append(v, out->inouts)
13807       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
13808       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
13809       #
13810       e9/jump loop/disp32
13811     }
13812     # save function outputs
13813     {
13814 $populate-mu-function-signature:check-for-out:
13815       (next-mu-token *(ebp+8) %ecx)
13816       (slice-empty? %ecx)  # => eax
13817       3d/compare-eax-and 0/imm32/false
13818       0f 85/jump-if-!= break/disp32
13819       # if (word-slice == '{') abort
13820       (slice-equal? %ecx "{")   # => eax
13821       3d/compare-eax-and 0/imm32/false
13822       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13823       # if (word-slice == '->') abort
13824       (slice-equal? %ecx "->")   # => eax
13825       3d/compare-eax-and 0/imm32/false
13826       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13827       # if (word-slice == '}') abort
13828       (slice-equal? %ecx "}")   # => eax
13829       3d/compare-eax-and 0/imm32/false
13830       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
13831       # v = parse-var-with-type(word-slice, first-line)
13832       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
13833       # assert(var->register != null)
13834       # . eax: (addr var) = lookup(v)
13835       (lookup *ebx *(ebx+4))  # => eax
13836       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
13837       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
13838       # out->outputs = append(v, out->outputs)
13839       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
13840       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
13841       #
13842       e9/jump loop/disp32
13843     }
13844 $populate-mu-function-signature:done:
13845     (check-no-tokens-left *(ebp+8))
13846 $populate-mu-function-signature:end:
13847     # . reclaim locals
13848     81 0/subop/add %esp 0x10/imm32
13849     # . restore registers
13850     5f/pop-to-edi
13851     5b/pop-to-ebx
13852     5a/pop-to-edx
13853     59/pop-to-ecx
13854     58/pop-to-eax
13855     # . epilogue
13856     89/<- %esp 5/r32/ebp
13857     5d/pop-to-ebp
13858     c3/return
13859 
13860 $populate-mu-function-signature:error1:
13861     # error("function signature not in form 'fn <name> {'")
13862     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
13863     (flush *(ebp+0x10))
13864     (rewind-stream *(ebp+8))
13865     (write-stream-data *(ebp+0x10) *(ebp+8))
13866     (write-buffered *(ebp+0x10) "'\n")
13867     (flush *(ebp+0x10))
13868     (stop *(ebp+0x14) 1)
13869     # never gets here
13870 
13871 $populate-mu-function-signature:error2:
13872     # error("fn " fn ": function inout '" var "' cannot be in a register")
13873     (write-buffered *(ebp+0x10) "fn ")
13874     50/push-eax
13875     (lookup *edi *(edi+4))  # Function-name Function-name => eax
13876     (write-buffered *(ebp+0x10) %eax)
13877     58/pop-to-eax
13878     (write-buffered *(ebp+0x10) ": function inout '")
13879     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13880     (write-buffered *(ebp+0x10) %eax)
13881     (write-buffered *(ebp+0x10) "' cannot be in a register")
13882     (flush *(ebp+0x10))
13883     (stop *(ebp+0x14) 1)
13884     # never gets here
13885 
13886 $populate-mu-function-signature:error3:
13887     # error("fn " fn ": function output '" var "' must be in a register")
13888     (write-buffered *(ebp+0x10) "fn ")
13889     50/push-eax
13890     (lookup *edi *(edi+4))  # Function-name Function-name => eax
13891     (write-buffered *(ebp+0x10) %eax)
13892     58/pop-to-eax
13893     (write-buffered *(ebp+0x10) ": function output '")
13894     (lookup *ebx *(ebx+4))  # => eax
13895     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13896     (write-buffered *(ebp+0x10) %eax)
13897     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
13898     (rewind-stream *(ebp+8))
13899     (write-stream-data *(ebp+0x10) *(ebp+8))
13900     (write-buffered *(ebp+0x10) "'\n")
13901     (flush *(ebp+0x10))
13902     (stop *(ebp+0x14) 1)
13903     # never gets here
13904 
13905 test-function-header-with-arg:
13906     # . prologue
13907     55/push-ebp
13908     89/<- %ebp 4/r32/esp
13909     # setup
13910     8b/-> *Primitive-type-ids 0/r32/eax
13911     89/<- *Type-id 0/r32/eax  # stream-write
13912     (clear-stream _test-input-stream)
13913     (write _test-input-stream "foo n: int {\n")
13914     # var result/ecx: function
13915     2b/subtract *Function-size 4/r32/esp
13916     89/<- %ecx 4/r32/esp
13917     (zero-out %ecx *Function-size)
13918     # var vars/ebx: (stack live-var 16)
13919     81 5/subop/subtract %esp 0xc0/imm32
13920     68/push 0xc0/imm32/size
13921     68/push 0/imm32/top
13922     89/<- %ebx 4/r32/esp
13923     # convert
13924     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
13925     # check result->name
13926     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
13927     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
13928     # var v/edx: (addr var) = result->inouts->value
13929     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
13930     (lookup *eax *(eax+4))  # List-value List-value => eax
13931     89/<- %edx 0/r32/eax
13932     # check v->name
13933     (lookup *edx *(edx+4))  # Var-name Var-name => eax
13934     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
13935     # check v->type
13936     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
13937     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
13938     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
13939     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
13940     # . epilogue
13941     89/<- %esp 5/r32/ebp
13942     5d/pop-to-ebp
13943     c3/return
13944 
13945 test-function-header-with-multiple-args:
13946     # . prologue
13947     55/push-ebp
13948     89/<- %ebp 4/r32/esp
13949     # setup
13950     8b/-> *Primitive-type-ids 0/r32/eax
13951     89/<- *Type-id 0/r32/eax  # stream-write
13952     (clear-stream _test-input-stream)
13953     (write _test-input-stream "foo a: int, b: int c: int {\n")
13954     # result/ecx: function
13955     2b/subtract *Function-size 4/r32/esp
13956     89/<- %ecx 4/r32/esp
13957     (zero-out %ecx *Function-size)
13958     # var vars/ebx: (stack live-var 16)
13959     81 5/subop/subtract %esp 0xc0/imm32
13960     68/push 0xc0/imm32/size
13961     68/push 0/imm32/top
13962     89/<- %ebx 4/r32/esp
13963     # convert
13964     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
13965     # check result->name
13966     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
13967     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
13968     # var inouts/edx: (addr list var) = lookup(result->inouts)
13969     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
13970     89/<- %edx 0/r32/eax
13971 $test-function-header-with-multiple-args:inout0:
13972     # var v/ebx: (addr var) = lookup(inouts->value)
13973     (lookup *edx *(edx+4))  # List-value List-value => eax
13974     89/<- %ebx 0/r32/eax
13975     # check v->name
13976     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
13977     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
13978     # check v->type
13979     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
13980     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
13981     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
13982     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
13983 $test-function-header-with-multiple-args:inout1:
13984     # inouts = lookup(inouts->next)
13985     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
13986     89/<- %edx 0/r32/eax
13987     # v = lookup(inouts->value)
13988     (lookup *edx *(edx+4))  # List-value List-value => eax
13989     89/<- %ebx 0/r32/eax
13990     # check v->name
13991     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
13992     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
13993     # check v->type
13994     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
13995     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
13996     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
13997     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
13998 $test-function-header-with-multiple-args:inout2:
13999     # inouts = lookup(inouts->next)
14000     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14001     89/<- %edx 0/r32/eax
14002     # v = lookup(inouts->value)
14003     (lookup *edx *(edx+4))  # List-value List-value => eax
14004     89/<- %ebx 0/r32/eax
14005     # check v->name
14006     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14007     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
14008     # check v->type
14009     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14010     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
14011     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
14012     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
14013     # . epilogue
14014     89/<- %esp 5/r32/ebp
14015     5d/pop-to-ebp
14016     c3/return
14017 
14018 test-function-header-with-multiple-args-and-outputs:
14019     # . prologue
14020     55/push-ebp
14021     89/<- %ebp 4/r32/esp
14022     # setup
14023     8b/-> *Primitive-type-ids 0/r32/eax
14024     89/<- *Type-id 0/r32/eax  # stream-write
14025     (clear-stream _test-input-stream)
14026     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
14027     # result/ecx: function
14028     2b/subtract *Function-size 4/r32/esp
14029     89/<- %ecx 4/r32/esp
14030     (zero-out %ecx *Function-size)
14031     # var vars/ebx: (stack live-var 16)
14032     81 5/subop/subtract %esp 0xc0/imm32
14033     68/push 0xc0/imm32/size
14034     68/push 0/imm32/top
14035     89/<- %ebx 4/r32/esp
14036     # convert
14037     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
14038     # check result->name
14039     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
14040     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
14041     # var inouts/edx: (addr list var) = lookup(result->inouts)
14042     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
14043     89/<- %edx 0/r32/eax
14044 $test-function-header-with-multiple-args-and-outputs:inout0:
14045     # var v/ebx: (addr var) = lookup(inouts->value)
14046     (lookup *edx *(edx+4))  # List-value List-value => eax
14047     89/<- %ebx 0/r32/eax
14048     # check v->name
14049     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14050     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
14051     # check v->type
14052     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14053     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
14054     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
14055     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
14056 $test-function-header-with-multiple-args-and-outputs:inout1:
14057     # inouts = lookup(inouts->next)
14058     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14059     89/<- %edx 0/r32/eax
14060     # v = lookup(inouts->value)
14061     (lookup *edx *(edx+4))  # List-value List-value => eax
14062     89/<- %ebx 0/r32/eax
14063     # check v->name
14064     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14065     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
14066     # check v->type
14067     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14068     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
14069     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
14070     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
14071 $test-function-header-with-multiple-args-and-outputs:inout2:
14072     # inouts = lookup(inouts->next)
14073     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14074     89/<- %edx 0/r32/eax
14075     # v = lookup(inouts->value)
14076     (lookup *edx *(edx+4))  # List-value List-value => eax
14077     89/<- %ebx 0/r32/eax
14078     # check v->name
14079     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14080     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
14081     # check v->type
14082     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14083     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
14084     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
14085     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
14086 $test-function-header-with-multiple-args-and-outputs:out0:
14087     # var outputs/edx: (addr list var) = lookup(result->outputs)
14088     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
14089     89/<- %edx 0/r32/eax
14090     # v = lookup(outputs->value)
14091     (lookup *edx *(edx+4))  # List-value List-value => eax
14092     89/<- %ebx 0/r32/eax
14093     # check v->name
14094     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14095     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
14096     # check v->register
14097     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
14098     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
14099     # check v->type
14100     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14101     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
14102     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
14103     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
14104 $test-function-header-with-multiple-args-and-outputs:out1:
14105     # outputs = lookup(outputs->next)
14106     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14107     89/<- %edx 0/r32/eax
14108     # v = lookup(inouts->value)
14109     (lookup *edx *(edx+4))  # List-value List-value => eax
14110     89/<- %ebx 0/r32/eax
14111     # check v->name
14112     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14113     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
14114     # check v->register
14115     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
14116     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
14117     # check v->type
14118     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14119     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
14120     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
14121     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
14122     # . epilogue
14123     89/<- %esp 5/r32/ebp
14124     5d/pop-to-ebp
14125     c3/return
14126 
14127 # format for variables with types
14128 #   x: int
14129 #   x: int,
14130 #   x/eax: int
14131 #   x/eax: int,
14132 # ignores at most one trailing comma
14133 # WARNING: modifies name
14134 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
14135     # pseudocode:
14136     #   var s: slice
14137     #   if (!slice-ends-with(name, ":"))
14138     #     abort
14139     #   --name->end to skip ':'
14140     #   next-token-from-slice(name->start, name->end, '/', s)
14141     #   new-var-from-slice(s, out)
14142     #   ## register
14143     #   next-token-from-slice(s->end, name->end, '/', s)
14144     #   if (!slice-empty?(s))
14145     #     out->register = slice-to-string(s)
14146     #   ## type
14147     #   var type: (handle type-tree) = parse-type(first-line)
14148     #   out->type = type
14149     #
14150     # . prologue
14151     55/push-ebp
14152     89/<- %ebp 4/r32/esp
14153     # . save registers
14154     50/push-eax
14155     51/push-ecx
14156     52/push-edx
14157     53/push-ebx
14158     56/push-esi
14159     57/push-edi
14160     # esi = name
14161     8b/-> *(ebp+8) 6/r32/esi
14162     # if (!slice-ends-with?(name, ":")) abort
14163     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
14164     49/decrement-ecx
14165     8a/copy-byte *ecx 1/r32/CL
14166     81 4/subop/and %ecx 0xff/imm32
14167     81 7/subop/compare %ecx 0x3a/imm32/colon
14168     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
14169     # --name->end to skip ':'
14170     ff 1/subop/decrement *(esi+4)
14171     # var s/ecx: slice
14172     68/push 0/imm32/end
14173     68/push 0/imm32/start
14174     89/<- %ecx 4/r32/esp
14175 $parse-var-with-type:parse-name:
14176     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
14177 $parse-var-with-type:create-var:
14178     # new-var-from-slice(s, out)
14179     (new-var-from-slice Heap %ecx *(ebp+0x10))
14180     # save out->register
14181 $parse-var-with-type:save-register:
14182     # . var out-addr/edi: (addr var) = lookup(*out)
14183     8b/-> *(ebp+0x10) 7/r32/edi
14184     (lookup *edi *(edi+4))  # => eax
14185     89/<- %edi 0/r32/eax
14186     # . s = next-token(...)
14187     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
14188     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
14189     {
14190 $parse-var-with-type:write-register:
14191       (slice-empty? %ecx)  # => eax
14192       3d/compare-eax-and 0/imm32/false
14193       75/jump-if-!= break/disp8
14194       # out->register = slice-to-string(s)
14195       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
14196       (slice-to-string Heap %ecx %eax)
14197     }
14198 $parse-var-with-type:save-type:
14199     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
14200     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14201 $parse-var-with-type:end:
14202     # . reclaim locals
14203     81 0/subop/add %esp 8/imm32
14204     # . restore registers
14205     5f/pop-to-edi
14206     5e/pop-to-esi
14207     5b/pop-to-ebx
14208     5a/pop-to-edx
14209     59/pop-to-ecx
14210     58/pop-to-eax
14211     # . epilogue
14212     89/<- %esp 5/r32/ebp
14213     5d/pop-to-ebp
14214     c3/return
14215 
14216 $parse-var-with-type:abort:
14217     # error("var should have form 'name: type' in '" line "'\n")
14218     (write-buffered *(ebp+0x14) "var should have form 'name: type' in '")
14219     (flush *(ebp+0x14))
14220     (rewind-stream *(ebp+0xc))
14221     (write-stream-data *(ebp+0x14) *(ebp+0xc))
14222     (write-buffered *(ebp+0x14) "'\n")
14223     (flush *(ebp+0x14))
14224     (stop *(ebp+0x18) 1)
14225     # never gets here
14226 
14227 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
14228     # pseudocode:
14229     #   var s: slice = next-mu-token(in)
14230     #   assert s != ""
14231     #   assert s != "->"
14232     #   assert s != "{"
14233     #   assert s != "}"
14234     #   if s == ")"
14235     #     return
14236     #   out = allocate(Type-tree)
14237     #   if s != "("
14238     #     HACK: if s is an int, parse and return it
14239     #     out->is-atom? = true
14240     #     if (s[0] == "_")
14241     #       out->value = type-parameter
14242     #       out->parameter-name = slice-to-string(ad, s)
14243     #     else
14244     #       out->value = pos-or-insert-slice(Type-id, s)
14245     #     return
14246     #   out->left = parse-type(ad, in)
14247     #   out->right = parse-type-tree(ad, in)
14248     #
14249     # . prologue
14250     55/push-ebp
14251     89/<- %ebp 4/r32/esp
14252     # . save registers
14253     50/push-eax
14254     51/push-ecx
14255     52/push-edx
14256     # clear out
14257     (zero-out *(ebp+0x10) *Handle-size)
14258     # var s/ecx: slice
14259     68/push 0/imm32
14260     68/push 0/imm32
14261     89/<- %ecx 4/r32/esp
14262     # s = next-mu-token(in)
14263     (next-mu-token *(ebp+0xc) %ecx)
14264 #?     (write-buffered Stderr "tok: ")
14265 #?     (write-slice-buffered Stderr %ecx)
14266 #?     (write-buffered Stderr "$\n")
14267 #?     (flush Stderr)
14268     # assert s != ""
14269     (slice-equal? %ecx "")  # => eax
14270     3d/compare-eax-and 0/imm32/false
14271     0f 85/jump-if-!= $parse-type:abort/disp32
14272     # assert s != "{"
14273     (slice-equal? %ecx "{")  # => eax
14274     3d/compare-eax-and 0/imm32/false
14275     0f 85/jump-if-!= $parse-type:abort/disp32
14276     # assert s != "}"
14277     (slice-equal? %ecx "}")  # => eax
14278     3d/compare-eax-and 0/imm32/false
14279     0f 85/jump-if-!= $parse-type:abort/disp32
14280     # assert s != "->"
14281     (slice-equal? %ecx "->")  # => eax
14282     3d/compare-eax-and 0/imm32/false
14283     0f 85/jump-if-!= $parse-type:abort/disp32
14284     # if (s == ")") return
14285     (slice-equal? %ecx ")")  # => eax
14286     3d/compare-eax-and 0/imm32/false
14287     0f 85/jump-if-!= $parse-type:end/disp32
14288     # out = new tree
14289     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
14290     # var out-addr/edx: (addr type-tree) = lookup(*out)
14291     8b/-> *(ebp+0x10) 2/r32/edx
14292     (lookup *edx *(edx+4))  # => eax
14293     89/<- %edx 0/r32/eax
14294     {
14295       # if (s != "(") break
14296       (slice-equal? %ecx "(")  # => eax
14297       3d/compare-eax-and 0/imm32/false
14298       0f 85/jump-if-!= break/disp32
14299       # if s is a number, store it in the type's size field
14300       {
14301 $parse-type:check-for-int:
14302         # var tmp/eax: byte = *s->slice
14303         8b/-> *ecx 0/r32/eax
14304         8a/copy-byte *eax 0/r32/AL
14305         81 4/subop/and %eax 0xff/imm32
14306         # TODO: raise an error on `var x: (array int a)`
14307         (is-decimal-digit? %eax)  # => eax
14308         3d/compare-eax-and 0/imm32/false
14309         74/jump-if-= break/disp8
14310         #
14311         (is-hex-int? %ecx)  # => eax
14312         3d/compare-eax-and 0/imm32/false
14313         74/jump-if-= break/disp8
14314 $parse-type:int:
14315         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
14316         (parse-hex-int-from-slice %ecx)  # => eax
14317         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
14318         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
14319         e9/jump $parse-type:end/disp32
14320       }
14321 $parse-type:atom:
14322       # out->is-atom? = true
14323       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
14324       {
14325 $parse-type:check-for-type-parameter:
14326         # var tmp/eax: byte = *s->slice
14327         8b/-> *ecx 0/r32/eax
14328         8a/copy-byte *eax 0/r32/AL
14329         81 4/subop/and %eax 0xff/imm32
14330         # if (tmp != '_') break
14331         3d/compare-eax-and 0x5f/imm32/_
14332         75/jump-if-!= break/disp8
14333 $parse-type:type-parameter:
14334         # out->value = type-parameter
14335         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
14336         # out->parameter-name = slice-to-string(ad, s)
14337         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
14338         (slice-to-string *(ebp+8) %ecx %eax)
14339         e9/jump $parse-type:end/disp32
14340       }
14341 $parse-type:non-type-parameter:
14342       # out->value = pos-or-insert-slice(Type-id, s)
14343       (pos-or-insert-slice Type-id %ecx)  # => eax
14344       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
14345       e9/jump $parse-type:end/disp32
14346     }
14347 $parse-type:non-atom:
14348     # otherwise s == "("
14349     # out->left = parse-type(ad, in)
14350     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
14351     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14352     # out->right = parse-type-tree(ad, in)
14353     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
14354     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14355 $parse-type:end:
14356     # . reclaim locals
14357     81 0/subop/add %esp 8/imm32
14358     # . restore registers
14359     5a/pop-to-edx
14360     59/pop-to-ecx
14361     58/pop-to-eax
14362     # . epilogue
14363     89/<- %esp 5/r32/ebp
14364     5d/pop-to-ebp
14365     c3/return
14366 
14367 $parse-type:abort:
14368     # error("unexpected token when parsing type: '" s "'\n")
14369     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
14370     (write-slice-buffered *(ebp+0x14) %ecx)
14371     (write-buffered *(ebp+0x14) "'\n")
14372     (flush *(ebp+0x14))
14373     (stop *(ebp+0x18) 1)
14374     # never gets here
14375 
14376 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
14377     # pseudocode:
14378     #   var tmp: (handle type-tree) = parse-type(ad, in)
14379     #   if tmp == 0
14380     #     return 0
14381     #   out = allocate(Type-tree)
14382     #   out->left = tmp
14383     #   out->right = parse-type-tree(ad, in)
14384     #
14385     # . prologue
14386     55/push-ebp
14387     89/<- %ebp 4/r32/esp
14388     # . save registers
14389     50/push-eax
14390     51/push-ecx
14391     52/push-edx
14392     #
14393     (zero-out *(ebp+0x10) *Handle-size)
14394     # var tmp/ecx: (handle type-tree)
14395     68/push 0/imm32
14396     68/push 0/imm32
14397     89/<- %ecx 4/r32/esp
14398     # tmp = parse-type(ad, in)
14399     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
14400     # if (tmp == 0) return
14401     81 7/subop/compare *ecx 0/imm32
14402     74/jump-if-= $parse-type-tree:end/disp8
14403     # out = new tree
14404     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
14405     # var out-addr/edx: (addr tree) = lookup(*out)
14406     8b/-> *(ebp+0x10) 2/r32/edx
14407     (lookup *edx *(edx+4))  # => eax
14408     89/<- %edx 0/r32/eax
14409     # out->left = tmp
14410     8b/-> *ecx 0/r32/eax
14411     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
14412     8b/-> *(ecx+4) 0/r32/eax
14413     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
14414     # out->right = parse-type-tree(ad, in)
14415     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
14416     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14417 $parse-type-tree:end:
14418     # . reclaim locals
14419     81 0/subop/add %esp 8/imm32
14420     # . restore registers
14421     5a/pop-to-edx
14422     59/pop-to-ecx
14423     58/pop-to-eax
14424     # . epilogue
14425     89/<- %esp 5/r32/ebp
14426     5d/pop-to-ebp
14427     c3/return
14428 
14429 next-mu-token:  # in: (addr stream byte), out: (addr slice)
14430     # pseudocode:
14431     # start:
14432     #   skip-chars-matching-whitespace(in)
14433     #   if in->read >= in->write              # end of in
14434     #     out = {0, 0}
14435     #     return
14436     #   out->start = &in->data[in->read]
14437     #   var curr-byte/eax: byte = in->data[in->read]
14438     #   if curr->byte == ','                  # comment token
14439     #     ++in->read
14440     #     goto start
14441     #   if curr-byte == '#'                   # comment
14442     #     goto done                             # treat as eof
14443     #   if curr-byte == '"'                   # string literal
14444     #     skip-string(in)
14445     #     goto done                           # no metadata
14446     #   if curr-byte == '('
14447     #     ++in->read
14448     #     goto done
14449     #   if curr-byte == ')'
14450     #     ++in->read
14451     #     goto done
14452     #   # read a word
14453     #   while true
14454     #     if in->read >= in->write
14455     #       break
14456     #     curr-byte = in->data[in->read]
14457     #     if curr-byte == ' '
14458     #       break
14459     #     if curr-byte == '\r'
14460     #       break
14461     #     if curr-byte == '\n'
14462     #       break
14463     #     if curr-byte == '('
14464     #       break
14465     #     if curr-byte == ')'
14466     #       break
14467     #     if curr-byte == ','
14468     #       break
14469     #     ++in->read
14470     # done:
14471     #   out->end = &in->data[in->read]
14472     #
14473     # . prologue
14474     55/push-ebp
14475     89/<- %ebp 4/r32/esp
14476     # . save registers
14477     50/push-eax
14478     51/push-ecx
14479     56/push-esi
14480     57/push-edi
14481     # esi = in
14482     8b/-> *(ebp+8) 6/r32/esi
14483     # edi = out
14484     8b/-> *(ebp+0xc) 7/r32/edi
14485 $next-mu-token:start:
14486     (skip-chars-matching-whitespace %esi)
14487 $next-mu-token:check0:
14488     # if (in->read >= in->write) return out = {0, 0}
14489     # . ecx = in->read
14490     8b/-> *(esi+4) 1/r32/ecx
14491     # . if (ecx >= in->write) return out = {0, 0}
14492     3b/compare<- *esi 1/r32/ecx
14493     c7 0/subop/copy *edi 0/imm32
14494     c7 0/subop/copy *(edi+4) 0/imm32
14495     0f 8d/jump-if->= $next-mu-token:end/disp32
14496     # out->start = &in->data[in->read]
14497     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
14498     89/<- *edi 0/r32/eax
14499     # var curr-byte/eax: byte = in->data[in->read]
14500     31/xor-with %eax 0/r32/eax
14501     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
14502     {
14503 $next-mu-token:check-for-comma:
14504       # if (curr-byte != ',') break
14505       3d/compare-eax-and 0x2c/imm32/comma
14506       75/jump-if-!= break/disp8
14507       # ++in->read
14508       ff 0/subop/increment *(esi+4)
14509       # restart
14510       e9/jump $next-mu-token:start/disp32
14511     }
14512     {
14513 $next-mu-token:check-for-comment:
14514       # if (curr-byte != '#') break
14515       3d/compare-eax-and 0x23/imm32/pound
14516       75/jump-if-!= break/disp8
14517       # return eof
14518       e9/jump $next-mu-token:done/disp32
14519     }
14520     {
14521 $next-mu-token:check-for-string-literal:
14522       # if (curr-byte != '"') break
14523       3d/compare-eax-and 0x22/imm32/dquote
14524       75/jump-if-!= break/disp8
14525       (skip-string %esi)
14526       # return
14527       e9/jump $next-mu-token:done/disp32
14528     }
14529     {
14530 $next-mu-token:check-for-open-paren:
14531       # if (curr-byte != '(') break
14532       3d/compare-eax-and 0x28/imm32/open-paren
14533       75/jump-if-!= break/disp8
14534       # ++in->read
14535       ff 0/subop/increment *(esi+4)
14536       # return
14537       e9/jump $next-mu-token:done/disp32
14538     }
14539     {
14540 $next-mu-token:check-for-close-paren:
14541       # if (curr-byte != ')') break
14542       3d/compare-eax-and 0x29/imm32/close-paren
14543       75/jump-if-!= break/disp8
14544       # ++in->read
14545       ff 0/subop/increment *(esi+4)
14546       # return
14547       e9/jump $next-mu-token:done/disp32
14548     }
14549     {
14550 $next-mu-token:regular-word-without-metadata:
14551       # if (in->read >= in->write) break
14552       # . ecx = in->read
14553       8b/-> *(esi+4) 1/r32/ecx
14554       # . if (ecx >= in->write) break
14555       3b/compare<- *esi 1/r32/ecx
14556       7d/jump-if->= break/disp8
14557       # var c/eax: byte = in->data[in->read]
14558       31/xor-with %eax 0/r32/eax
14559       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
14560       # if (c == ' ') break
14561       3d/compare-eax-and 0x20/imm32/space
14562       74/jump-if-= break/disp8
14563       # if (c == '\r') break
14564       3d/compare-eax-and 0xd/imm32/carriage-return
14565       74/jump-if-= break/disp8
14566       # if (c == '\n') break
14567       3d/compare-eax-and 0xa/imm32/newline
14568       74/jump-if-= break/disp8
14569       # if (c == '(') break
14570       3d/compare-eax-and 0x28/imm32/open-paren
14571       0f 84/jump-if-= break/disp32
14572       # if (c == ')') break
14573       3d/compare-eax-and 0x29/imm32/close-paren
14574       0f 84/jump-if-= break/disp32
14575       # if (c == ',') break
14576       3d/compare-eax-and 0x2c/imm32/comma
14577       0f 84/jump-if-= break/disp32
14578       # ++in->read
14579       ff 0/subop/increment *(esi+4)
14580       #
14581       e9/jump loop/disp32
14582     }
14583 $next-mu-token:done:
14584     # out->end = &in->data[in->read]
14585     8b/-> *(esi+4) 1/r32/ecx
14586     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
14587     89/<- *(edi+4) 0/r32/eax
14588 $next-mu-token:end:
14589     # . restore registers
14590     5f/pop-to-edi
14591     5e/pop-to-esi
14592     59/pop-to-ecx
14593     58/pop-to-eax
14594     # . epilogue
14595     89/<- %esp 5/r32/ebp
14596     5d/pop-to-ebp
14597     c3/return
14598 
14599 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
14600     # . prologue
14601     55/push-ebp
14602     89/<- %ebp 4/r32/esp
14603     # if (pos-slice(arr, s) != -1) return it
14604     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
14605     3d/compare-eax-and -1/imm32
14606     75/jump-if-!= $pos-or-insert-slice:end/disp8
14607 $pos-or-insert-slice:insert:
14608     # var s2/eax: (handle array byte)
14609     68/push 0/imm32
14610     68/push 0/imm32
14611     89/<- %eax 4/r32/esp
14612     (slice-to-string Heap *(ebp+0xc) %eax)
14613     # throw away alloc-id
14614     (lookup *eax *(eax+4))  # => eax
14615     (write-int *(ebp+8) %eax)
14616     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
14617 $pos-or-insert-slice:end:
14618     # . reclaim locals
14619     81 0/subop/add %esp 8/imm32
14620     # . epilogue
14621     89/<- %esp 5/r32/ebp
14622     5d/pop-to-ebp
14623     c3/return
14624 
14625 # return the index in an array of strings matching 's', -1 if not found
14626 # index is denominated in elements, not bytes
14627 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
14628     # . prologue
14629     55/push-ebp
14630     89/<- %ebp 4/r32/esp
14631     # . save registers
14632     51/push-ecx
14633     52/push-edx
14634     53/push-ebx
14635     56/push-esi
14636 #?     (write-buffered Stderr "pos-slice: ")
14637 #?     (write-slice-buffered Stderr *(ebp+0xc))
14638 #?     (write-buffered Stderr "\n")
14639 #?     (flush Stderr)
14640     # esi = arr
14641     8b/-> *(ebp+8) 6/r32/esi
14642     # var index/ecx: int = 0
14643     b9/copy-to-ecx 0/imm32
14644     # var curr/edx: (addr (addr array byte)) = arr->data
14645     8d/copy-address *(esi+0xc) 2/r32/edx
14646     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
14647     8b/-> *esi 3/r32/ebx
14648     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
14649     {
14650 #?       (write-buffered Stderr "  ")
14651 #?       (write-int32-hex-buffered Stderr %ecx)
14652 #?       (write-buffered Stderr "\n")
14653 #?       (flush Stderr)
14654       # if (curr >= max) return -1
14655       39/compare %edx 3/r32/ebx
14656       b8/copy-to-eax -1/imm32
14657       73/jump-if-addr>= $pos-slice:end/disp8
14658       # if (slice-equal?(s, *curr)) break
14659       (slice-equal? *(ebp+0xc) *edx)  # => eax
14660       3d/compare-eax-and 0/imm32/false
14661       75/jump-if-!= break/disp8
14662       # ++index
14663       41/increment-ecx
14664       # curr += 4
14665       81 0/subop/add %edx 4/imm32
14666       #
14667       eb/jump loop/disp8
14668     }
14669     # return index
14670     89/<- %eax 1/r32/ecx
14671 $pos-slice:end:
14672 #?     (write-buffered Stderr "=> ")
14673 #?     (write-int32-hex-buffered Stderr %eax)
14674 #?     (write-buffered Stderr "\n")
14675     # . restore registers
14676     5e/pop-to-esi
14677     5b/pop-to-ebx
14678     5a/pop-to-edx
14679     59/pop-to-ecx
14680     # . epilogue
14681     89/<- %esp 5/r32/ebp
14682     5d/pop-to-ebp
14683     c3/return
14684 
14685 test-parse-var-with-type:
14686     # . prologue
14687     55/push-ebp
14688     89/<- %ebp 4/r32/esp
14689     # setup
14690     8b/-> *Primitive-type-ids 0/r32/eax
14691     89/<- *Type-id 0/r32/eax  # stream-write
14692     # (eax..ecx) = "x:"
14693     b8/copy-to-eax "x:"/imm32
14694     8b/-> *eax 1/r32/ecx
14695     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14696     05/add-to-eax 4/imm32
14697     # var slice/ecx: slice = {eax, ecx}
14698     51/push-ecx
14699     50/push-eax
14700     89/<- %ecx 4/r32/esp
14701     # _test-input-stream contains "int"
14702     (clear-stream _test-input-stream)
14703     (write _test-input-stream "int")
14704     # var v/edx: (handle var)
14705     68/push 0/imm32
14706     68/push 0/imm32
14707     89/<- %edx 4/r32/esp
14708     #
14709     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
14710     # var v-addr/edx: (addr var) = lookup(v)
14711     (lookup *edx *(edx+4))  # => eax
14712     89/<- %edx 0/r32/eax
14713     # check v-addr->name
14714     (lookup *edx *(edx+4))  # Var-name Var-name => eax
14715     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
14716     # check v-addr->type
14717     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
14718     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
14719     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
14720     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
14721     # . epilogue
14722     89/<- %esp 5/r32/ebp
14723     5d/pop-to-ebp
14724     c3/return
14725 
14726 test-parse-var-with-type-and-register:
14727     # . prologue
14728     55/push-ebp
14729     89/<- %ebp 4/r32/esp
14730     # setup
14731     8b/-> *Primitive-type-ids 0/r32/eax
14732     89/<- *Type-id 0/r32/eax  # stream-write
14733     # (eax..ecx) = "x/eax:"
14734     b8/copy-to-eax "x/eax:"/imm32
14735     8b/-> *eax 1/r32/ecx
14736     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14737     05/add-to-eax 4/imm32
14738     # var slice/ecx: slice = {eax, ecx}
14739     51/push-ecx
14740     50/push-eax
14741     89/<- %ecx 4/r32/esp
14742     # _test-input-stream contains "int"
14743     (clear-stream _test-input-stream)
14744     (write _test-input-stream "int")
14745     # var v/edx: (handle var)
14746     68/push 0/imm32
14747     68/push 0/imm32
14748     89/<- %edx 4/r32/esp
14749     #
14750     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
14751     # var v-addr/edx: (addr var) = lookup(v)
14752     (lookup *edx *(edx+4))  # => eax
14753     89/<- %edx 0/r32/eax
14754     # check v-addr->name
14755     (lookup *edx *(edx+4))  # Var-name Var-name => eax
14756     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
14757     # check v-addr->register
14758     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
14759     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
14760     # check v-addr->type
14761     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
14762     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
14763     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
14764     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
14765     # . epilogue
14766     89/<- %esp 5/r32/ebp
14767     5d/pop-to-ebp
14768     c3/return
14769 
14770 test-parse-var-with-trailing-characters:
14771     # . prologue
14772     55/push-ebp
14773     89/<- %ebp 4/r32/esp
14774     # setup
14775     8b/-> *Primitive-type-ids 0/r32/eax
14776     89/<- *Type-id 0/r32/eax  # stream-write
14777     # (eax..ecx) = "x:"
14778     b8/copy-to-eax "x:"/imm32
14779     8b/-> *eax 1/r32/ecx
14780     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14781     05/add-to-eax 4/imm32
14782     # var slice/ecx: slice = {eax, ecx}
14783     51/push-ecx
14784     50/push-eax
14785     89/<- %ecx 4/r32/esp
14786     # _test-input-stream contains "int,"
14787     (clear-stream _test-input-stream)
14788     (write _test-input-stream "int,")
14789     # var v/edx: (handle var)
14790     68/push 0/imm32
14791     68/push 0/imm32
14792     89/<- %edx 4/r32/esp
14793     #
14794     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
14795     # var v-addr/edx: (addr var) = lookup(v)
14796     (lookup *edx *(edx+4))  # => eax
14797     89/<- %edx 0/r32/eax
14798     # check v-addr->name
14799     (lookup *edx *(edx+4))  # Var-name Var-name => eax
14800     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
14801     # check v-addr->register
14802     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
14803     # check v-addr->type
14804     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
14805     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
14806     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
14807     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
14808     # . epilogue
14809     89/<- %esp 5/r32/ebp
14810     5d/pop-to-ebp
14811     c3/return
14812 
14813 test-parse-var-with-register-and-trailing-characters:
14814     # . prologue
14815     55/push-ebp
14816     89/<- %ebp 4/r32/esp
14817     # setup
14818     8b/-> *Primitive-type-ids 0/r32/eax
14819     89/<- *Type-id 0/r32/eax  # stream-write
14820     # (eax..ecx) = "x/eax:"
14821     b8/copy-to-eax "x/eax:"/imm32
14822     8b/-> *eax 1/r32/ecx
14823     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14824     05/add-to-eax 4/imm32
14825     # var slice/ecx: slice = {eax, ecx}
14826     51/push-ecx
14827     50/push-eax
14828     89/<- %ecx 4/r32/esp
14829     # _test-input-stream contains "int,"
14830     (clear-stream _test-input-stream)
14831     (write _test-input-stream "int,")
14832     # var v/edx: (handle var)
14833     68/push 0/imm32
14834     68/push 0/imm32
14835     89/<- %edx 4/r32/esp
14836     #
14837     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
14838     # var v-addr/edx: (addr var) = lookup(v)
14839     (lookup *edx *(edx+4))  # => eax
14840     89/<- %edx 0/r32/eax
14841     # check v-addr->name
14842     (lookup *edx *(edx+4))  # Var-name Var-name => eax
14843     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
14844     # check v-addr->register
14845     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
14846     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
14847     # check v-addr->type
14848     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
14849     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
14850     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
14851     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
14852     # . epilogue
14853     89/<- %esp 5/r32/ebp
14854     5d/pop-to-ebp
14855     c3/return
14856 
14857 test-parse-var-with-compound-type:
14858     # . prologue
14859     55/push-ebp
14860     89/<- %ebp 4/r32/esp
14861     # setup
14862     8b/-> *Primitive-type-ids 0/r32/eax
14863     89/<- *Type-id 0/r32/eax  # stream-write
14864     # (eax..ecx) = "x:"
14865     b8/copy-to-eax "x:"/imm32
14866     8b/-> *eax 1/r32/ecx
14867     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14868     05/add-to-eax 4/imm32
14869     # var slice/ecx: slice = {eax, ecx}
14870     51/push-ecx
14871     50/push-eax
14872     89/<- %ecx 4/r32/esp
14873     # _test-input-stream contains "(addr int)"
14874     (clear-stream _test-input-stream)
14875     (write _test-input-stream "(addr int)")
14876     # var v/edx: (handle var)
14877     68/push 0/imm32
14878     68/push 0/imm32
14879     89/<- %edx 4/r32/esp
14880     #
14881     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
14882     # var v-addr/edx: (addr var) = lookup(v)
14883     (lookup *edx *(edx+4))  # => eax
14884     89/<- %edx 0/r32/eax
14885     # check v-addr->name
14886     (lookup *edx *(edx+4))  # Var-name Var-name => eax
14887     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
14888     # check v-addr->register
14889     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
14890     # - check v-addr->type
14891     # var type/edx: (addr type-tree) = var->type
14892     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
14893     89/<- %edx 0/r32/eax
14894     # type is a non-atom
14895     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
14896     # type->left == atom(addr)
14897     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
14898     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
14899     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
14900     # type->right->left == atom(int)
14901     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
14902     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
14903     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
14904     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
14905     # type->right->right == null
14906     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
14907     # . epilogue
14908     89/<- %esp 5/r32/ebp
14909     5d/pop-to-ebp
14910     c3/return
14911 
14912 # identifier starts with a letter or '$' or '_'
14913 # no constraints at the moment on later letters
14914 # all we really want to do so far is exclude '{', '}' and '->'
14915 is-identifier?:  # in: (addr slice) -> result/eax: boolean
14916     # . prologue
14917     55/push-ebp
14918     89/<- %ebp 4/r32/esp
14919     # if (slice-empty?(in)) return false
14920     (slice-empty? *(ebp+8))  # => eax
14921     3d/compare-eax-and 0/imm32/false
14922     75/jump-if-!= $is-identifier?:false/disp8
14923     # var c/eax: byte = *in->start
14924     8b/-> *(ebp+8) 0/r32/eax
14925     8b/-> *eax 0/r32/eax
14926     8a/copy-byte *eax 0/r32/AL
14927     81 4/subop/and %eax 0xff/imm32
14928     # if (c == '$') return true
14929     3d/compare-eax-and 0x24/imm32/$
14930     74/jump-if-= $is-identifier?:true/disp8
14931     # if (c == '_') return true
14932     3d/compare-eax-and 0x5f/imm32/_
14933     74/jump-if-= $is-identifier?:true/disp8
14934     # drop case
14935     25/and-eax-with 0x5f/imm32
14936     # if (c < 'A') return false
14937     3d/compare-eax-and 0x41/imm32/A
14938     7c/jump-if-< $is-identifier?:false/disp8
14939     # if (c > 'Z') return false
14940     3d/compare-eax-and 0x5a/imm32/Z
14941     7f/jump-if-> $is-identifier?:false/disp8
14942     # otherwise return true
14943 $is-identifier?:true:
14944     b8/copy-to-eax 1/imm32/true
14945     eb/jump $is-identifier?:end/disp8
14946 $is-identifier?:false:
14947     b8/copy-to-eax 0/imm32/false
14948 $is-identifier?:end:
14949     # . epilogue
14950     89/<- %esp 5/r32/ebp
14951     5d/pop-to-ebp
14952     c3/return
14953 
14954 test-is-identifier-dollar:
14955     # . prologue
14956     55/push-ebp
14957     89/<- %ebp 4/r32/esp
14958     # (eax..ecx) = "$a"
14959     b8/copy-to-eax "$a"/imm32
14960     8b/-> *eax 1/r32/ecx
14961     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14962     05/add-to-eax 4/imm32
14963     # var slice/ecx: slice = {eax, ecx}
14964     51/push-ecx
14965     50/push-eax
14966     89/<- %ecx 4/r32/esp
14967     #
14968     (is-identifier? %ecx)
14969     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
14970     # . epilogue
14971     89/<- %esp 5/r32/ebp
14972     5d/pop-to-ebp
14973     c3/return
14974 
14975 test-is-identifier-underscore:
14976     # . prologue
14977     55/push-ebp
14978     89/<- %ebp 4/r32/esp
14979     # (eax..ecx) = "_a"
14980     b8/copy-to-eax "_a"/imm32
14981     8b/-> *eax 1/r32/ecx
14982     8d/copy-address *(eax+ecx+4) 1/r32/ecx
14983     05/add-to-eax 4/imm32
14984     # var slice/ecx: slice = {eax, ecx}
14985     51/push-ecx
14986     50/push-eax
14987     89/<- %ecx 4/r32/esp
14988     #
14989     (is-identifier? %ecx)
14990     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
14991     # . epilogue
14992     89/<- %esp 5/r32/ebp
14993     5d/pop-to-ebp
14994     c3/return
14995 
14996 test-is-identifier-a:
14997     # . prologue
14998     55/push-ebp
14999     89/<- %ebp 4/r32/esp
15000     # (eax..ecx) = "a$"
15001     b8/copy-to-eax "a$"/imm32
15002     8b/-> *eax 1/r32/ecx
15003     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15004     05/add-to-eax 4/imm32
15005     # var slice/ecx: slice = {eax, ecx}
15006     51/push-ecx
15007     50/push-eax
15008     89/<- %ecx 4/r32/esp
15009     #
15010     (is-identifier? %ecx)
15011     (check-ints-equal %eax 1 "F - test-is-identifier-a")
15012     # . epilogue
15013     89/<- %esp 5/r32/ebp
15014     5d/pop-to-ebp
15015     c3/return
15016 
15017 test-is-identifier-z:
15018     # . prologue
15019     55/push-ebp
15020     89/<- %ebp 4/r32/esp
15021     # (eax..ecx) = "z$"
15022     b8/copy-to-eax "z$"/imm32
15023     8b/-> *eax 1/r32/ecx
15024     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15025     05/add-to-eax 4/imm32
15026     # var slice/ecx: slice = {eax, ecx}
15027     51/push-ecx
15028     50/push-eax
15029     89/<- %ecx 4/r32/esp
15030     #
15031     (is-identifier? %ecx)
15032     (check-ints-equal %eax 1 "F - test-is-identifier-z")
15033     # . epilogue
15034     89/<- %esp 5/r32/ebp
15035     5d/pop-to-ebp
15036     c3/return
15037 
15038 test-is-identifier-A:
15039     # . prologue
15040     55/push-ebp
15041     89/<- %ebp 4/r32/esp
15042     # (eax..ecx) = "A$"
15043     b8/copy-to-eax "A$"/imm32
15044     8b/-> *eax 1/r32/ecx
15045     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15046     05/add-to-eax 4/imm32
15047     # var slice/ecx: slice = {eax, ecx}
15048     51/push-ecx
15049     50/push-eax
15050     89/<- %ecx 4/r32/esp
15051     #
15052     (is-identifier? %ecx)
15053     (check-ints-equal %eax 1 "F - test-is-identifier-A")
15054     # . epilogue
15055     89/<- %esp 5/r32/ebp
15056     5d/pop-to-ebp
15057     c3/return
15058 
15059 test-is-identifier-Z:
15060     # . prologue
15061     55/push-ebp
15062     89/<- %ebp 4/r32/esp
15063     # (eax..ecx) = "Z$"
15064     b8/copy-to-eax "Z$"/imm32
15065     8b/-> *eax 1/r32/ecx
15066     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15067     05/add-to-eax 4/imm32
15068     # var slice/ecx: slice = {eax, ecx}
15069     51/push-ecx
15070     50/push-eax
15071     89/<- %ecx 4/r32/esp
15072     #
15073     (is-identifier? %ecx)
15074     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
15075     # . epilogue
15076     89/<- %esp 5/r32/ebp
15077     5d/pop-to-ebp
15078     c3/return
15079 
15080 test-is-identifier-at:
15081     # character before 'A' is invalid
15082     # . prologue
15083     55/push-ebp
15084     89/<- %ebp 4/r32/esp
15085     # (eax..ecx) = "@a"
15086     b8/copy-to-eax "@a"/imm32
15087     8b/-> *eax 1/r32/ecx
15088     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15089     05/add-to-eax 4/imm32
15090     # var slice/ecx: slice = {eax, ecx}
15091     51/push-ecx
15092     50/push-eax
15093     89/<- %ecx 4/r32/esp
15094     #
15095     (is-identifier? %ecx)
15096     (check-ints-equal %eax 0 "F - test-is-identifier-@")
15097     # . epilogue
15098     89/<- %esp 5/r32/ebp
15099     5d/pop-to-ebp
15100     c3/return
15101 
15102 test-is-identifier-square-bracket:
15103     # character after 'Z' is invalid
15104     # . prologue
15105     55/push-ebp
15106     89/<- %ebp 4/r32/esp
15107     # (eax..ecx) = "[a"
15108     b8/copy-to-eax "[a"/imm32
15109     8b/-> *eax 1/r32/ecx
15110     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15111     05/add-to-eax 4/imm32
15112     # var slice/ecx: slice = {eax, ecx}
15113     51/push-ecx
15114     50/push-eax
15115     89/<- %ecx 4/r32/esp
15116     #
15117     (is-identifier? %ecx)
15118     (check-ints-equal %eax 0 "F - test-is-identifier-@")
15119     # . epilogue
15120     89/<- %esp 5/r32/ebp
15121     5d/pop-to-ebp
15122     c3/return
15123 
15124 test-is-identifier-backtick:
15125     # character before 'a' is invalid
15126     # . prologue
15127     55/push-ebp
15128     89/<- %ebp 4/r32/esp
15129     # (eax..ecx) = "`a"
15130     b8/copy-to-eax "`a"/imm32
15131     8b/-> *eax 1/r32/ecx
15132     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15133     05/add-to-eax 4/imm32
15134     # var slice/ecx: slice = {eax, ecx}
15135     51/push-ecx
15136     50/push-eax
15137     89/<- %ecx 4/r32/esp
15138     #
15139     (is-identifier? %ecx)
15140     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
15141     # . epilogue
15142     89/<- %esp 5/r32/ebp
15143     5d/pop-to-ebp
15144     c3/return
15145 
15146 test-is-identifier-curly-brace-open:
15147     # character after 'z' is invalid; also used for blocks
15148     # . prologue
15149     55/push-ebp
15150     89/<- %ebp 4/r32/esp
15151     # (eax..ecx) = "{a"
15152     b8/copy-to-eax "{a"/imm32
15153     8b/-> *eax 1/r32/ecx
15154     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15155     05/add-to-eax 4/imm32
15156     # var slice/ecx: slice = {eax, ecx}
15157     51/push-ecx
15158     50/push-eax
15159     89/<- %ecx 4/r32/esp
15160     #
15161     (is-identifier? %ecx)
15162     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
15163     # . epilogue
15164     89/<- %esp 5/r32/ebp
15165     5d/pop-to-ebp
15166     c3/return
15167 
15168 test-is-identifier-curly-brace-close:
15169     # . prologue
15170     55/push-ebp
15171     89/<- %ebp 4/r32/esp
15172     # (eax..ecx) = "}a"
15173     b8/copy-to-eax "}a"/imm32
15174     8b/-> *eax 1/r32/ecx
15175     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15176     05/add-to-eax 4/imm32
15177     # var slice/ecx: slice = {eax, ecx}
15178     51/push-ecx
15179     50/push-eax
15180     89/<- %ecx 4/r32/esp
15181     #
15182     (is-identifier? %ecx)
15183     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
15184     # . epilogue
15185     89/<- %esp 5/r32/ebp
15186     5d/pop-to-ebp
15187     c3/return
15188 
15189 test-is-identifier-hyphen:
15190     # disallow leading '-' since '->' has special meaning
15191     # . prologue
15192     55/push-ebp
15193     89/<- %ebp 4/r32/esp
15194     # (eax..ecx) = "-a"
15195     b8/copy-to-eax "-a"/imm32
15196     8b/-> *eax 1/r32/ecx
15197     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15198     05/add-to-eax 4/imm32
15199     # var slice/ecx: slice = {eax, ecx}
15200     51/push-ecx
15201     50/push-eax
15202     89/<- %ecx 4/r32/esp
15203     #
15204     (is-identifier? %ecx)
15205     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
15206     # . epilogue
15207     89/<- %esp 5/r32/ebp
15208     5d/pop-to-ebp
15209     c3/return
15210 
15211 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
15212     # . prologue
15213     55/push-ebp
15214     89/<- %ebp 4/r32/esp
15215     # . save registers
15216     50/push-eax
15217     56/push-esi
15218     57/push-edi
15219     # esi = in
15220     8b/-> *(ebp+8) 6/r32/esi
15221     # edi = out
15222     8b/-> *(ebp+0xc) 7/r32/edi
15223     # initialize some global state
15224     c7 0/subop/copy *Curr-block-depth 1/imm32
15225     # parse-mu-block(in, vars, out, out->body)
15226     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
15227     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
15228 $populate-mu-function-body:end:
15229     # . restore registers
15230     5f/pop-to-edi
15231     5e/pop-to-esi
15232     58/pop-to-eax
15233     # . epilogue
15234     89/<- %esp 5/r32/ebp
15235     5d/pop-to-ebp
15236     c3/return
15237 
15238 # parses a block, assuming that the leading '{' has already been read by the caller
15239 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)
15240     # pseudocode:
15241     #   var line: (stream byte 512)
15242     #   var word-slice: slice
15243     #   allocate(Heap, Stmt-size, out)
15244     #   var out-addr: (addr block) = lookup(*out)
15245     #   out-addr->tag = 0/block
15246     #   out-addr->var = some unique name
15247     #   push(vars, {out-addr->var, false})
15248     #   while true                                  # line loop
15249     #     clear-stream(line)
15250     #     read-line-buffered(in, line)
15251     #     if (line->write == 0) break               # end of file
15252     #     word-slice = next-mu-token(line)
15253     #     if slice-empty?(word-slice)               # end of line
15254     #       continue
15255     #     else if slice-starts-with?(word-slice, "#")
15256     #       continue
15257     #     else if slice-equal?(word-slice, "{")
15258     #       assert(no-tokens-in(line))
15259     #       block = parse-mu-block(in, vars, fn)
15260     #       append-to-block(out-addr, block)
15261     #     else if slice-equal?(word-slice, "}")
15262     #       break
15263     #     else if slice-ends-with?(word-slice, ":")
15264     #       # TODO: error-check the rest of 'line'
15265     #       --word-slice->end to skip ':'
15266     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
15267     #       append-to-block(out-addr, named-block)
15268     #     else if slice-equal?(word-slice, "var")
15269     #       var-def = parse-mu-var-def(line, vars, fn)
15270     #       append-to-block(out-addr, var-def)
15271     #     else
15272     #       stmt = parse-mu-stmt(line, vars, fn)
15273     #       append-to-block(out-addr, stmt)
15274     #   pop(vars)
15275     #
15276     # . prologue
15277     55/push-ebp
15278     89/<- %ebp 4/r32/esp
15279     # . save registers
15280     50/push-eax
15281     51/push-ecx
15282     52/push-edx
15283     53/push-ebx
15284     57/push-edi
15285     # var line/ecx: (stream byte 512)
15286     81 5/subop/subtract %esp 0x200/imm32
15287     68/push 0x200/imm32/size
15288     68/push 0/imm32/read
15289     68/push 0/imm32/write
15290     89/<- %ecx 4/r32/esp
15291     # var word-slice/edx: slice
15292     68/push 0/imm32/end
15293     68/push 0/imm32/start
15294     89/<- %edx 4/r32/esp
15295     # allocate into out
15296     (allocate Heap *Stmt-size *(ebp+0x14))
15297     # var out-addr/edi: (addr block) = lookup(*out)
15298     8b/-> *(ebp+0x14) 7/r32/edi
15299     (lookup *edi *(edi+4))  # => eax
15300     89/<- %edi 0/r32/eax
15301     # out-addr->tag is 0 (block) by default
15302     # set out-addr->var
15303     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
15304     (new-block-name *(ebp+0x10) %eax)
15305     # push(vars, out-addr->var)
15306     (push *(ebp+0xc) *(edi+0xc))  # Block-var
15307     (push *(ebp+0xc) *(edi+0x10))  # Block-var
15308     (push *(ebp+0xc) 0)  # false
15309     # increment *Curr-block-depth
15310     ff 0/subop/increment *Curr-block-depth
15311     {
15312 $parse-mu-block:line-loop:
15313       # line = read-line-buffered(in)
15314       (clear-stream %ecx)
15315       (read-line-buffered *(ebp+8) %ecx)
15316 #?       (write-buffered Stderr "line: ")
15317 #?       (write-stream-data Stderr %ecx)
15318 #? #?       (write-buffered Stderr Newline)  # line has its own newline
15319 #?       (flush Stderr)
15320 #?       (rewind-stream %ecx)
15321       # if (line->write == 0) break
15322       81 7/subop/compare *ecx 0/imm32
15323       0f 84/jump-if-= break/disp32
15324 #?       (write-buffered Stderr "vars:\n")
15325 #?       (dump-vars *(ebp+0xc))
15326       # word-slice = next-mu-token(line)
15327       (next-mu-token %ecx %edx)
15328 #?       (write-buffered Stderr "word: ")
15329 #?       (write-slice-buffered Stderr %edx)
15330 #?       (write-buffered Stderr Newline)
15331 #?       (flush Stderr)
15332       # if slice-empty?(word-slice) continue
15333       (slice-empty? %edx)
15334       3d/compare-eax-and 0/imm32/false
15335       0f 85/jump-if-!= loop/disp32
15336       # if (slice-starts-with?(word-slice, '#') continue
15337       # . eax = *word-slice->start
15338       8b/-> *edx 0/r32/eax
15339       8a/copy-byte *eax 0/r32/AL
15340       81 4/subop/and %eax 0xff/imm32
15341       # . if (eax == '#') continue
15342       3d/compare-eax-and 0x23/imm32/hash
15343       0f 84/jump-if-= loop/disp32
15344       # if slice-equal?(word-slice, "{")
15345       {
15346 $parse-mu-block:check-for-block:
15347         (slice-equal? %edx "{")
15348         3d/compare-eax-and 0/imm32/false
15349         74/jump-if-= break/disp8
15350         (check-no-tokens-left %ecx)
15351         # parse new block and append
15352         # . var tmp/eax: (handle block)
15353         68/push 0/imm32
15354         68/push 0/imm32
15355         89/<- %eax 4/r32/esp
15356         # .
15357         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
15358         (append-to-block Heap %edi  *eax *(eax+4))
15359         # . reclaim tmp
15360         81 0/subop/add %esp 8/imm32
15361         # .
15362         e9/jump $parse-mu-block:line-loop/disp32
15363       }
15364       # if slice-equal?(word-slice, "}") break
15365 $parse-mu-block:check-for-end:
15366       (slice-equal? %edx "}")
15367       3d/compare-eax-and 0/imm32/false
15368       0f 85/jump-if-!= break/disp32
15369       # if slice-ends-with?(word-slice, ":") parse named block and append
15370       {
15371 $parse-mu-block:check-for-named-block:
15372         # . eax = *(word-slice->end-1)
15373         8b/-> *(edx+4) 0/r32/eax
15374         48/decrement-eax
15375         8a/copy-byte *eax 0/r32/AL
15376         81 4/subop/and %eax 0xff/imm32
15377         # . if (eax != ':') break
15378         3d/compare-eax-and 0x3a/imm32/colon
15379         0f 85/jump-if-!= break/disp32
15380         # TODO: error-check the rest of 'line'
15381         #
15382         # skip ':'
15383         ff 1/subop/decrement *(edx+4)  # Slice-end
15384         # var tmp/eax: (handle block)
15385         68/push 0/imm32
15386         68/push 0/imm32
15387         89/<- %eax 4/r32/esp
15388         #
15389         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
15390         (append-to-block Heap %edi  *eax *(eax+4))
15391         # reclaim tmp
15392         81 0/subop/add %esp 8/imm32
15393         #
15394         e9/jump $parse-mu-block:line-loop/disp32
15395       }
15396       # if slice-equal?(word-slice, "var")
15397       {
15398 $parse-mu-block:check-for-var:
15399         (slice-equal? %edx "var")
15400         3d/compare-eax-and 0/imm32/false
15401         74/jump-if-= break/disp8
15402         # var tmp/eax: (handle block)
15403         68/push 0/imm32
15404         68/push 0/imm32
15405         89/<- %eax 4/r32/esp
15406         #
15407         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
15408         (append-to-block Heap %edi  *eax *(eax+4))
15409         # reclaim tmp
15410         81 0/subop/add %esp 8/imm32
15411         #
15412         e9/jump $parse-mu-block:line-loop/disp32
15413       }
15414 $parse-mu-block:regular-stmt:
15415       # otherwise
15416       # var tmp/eax: (handle block)
15417       68/push 0/imm32
15418       68/push 0/imm32
15419       89/<- %eax 4/r32/esp
15420       #
15421       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
15422       (append-to-block Heap %edi  *eax *(eax+4))
15423       # reclaim tmp
15424       81 0/subop/add %esp 8/imm32
15425       #
15426       e9/jump loop/disp32
15427     } # end line loop
15428     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
15429     # decrement *Curr-block-depth
15430     ff 1/subop/decrement *Curr-block-depth
15431     # pop(vars)
15432     (pop *(ebp+0xc))  # => eax
15433     (pop *(ebp+0xc))  # => eax
15434     (pop *(ebp+0xc))  # => eax
15435 $parse-mu-block:end:
15436     # . reclaim locals
15437     81 0/subop/add %esp 0x214/imm32
15438     # . restore registers
15439     5f/pop-to-edi
15440     5b/pop-to-ebx
15441     5a/pop-to-edx
15442     59/pop-to-ecx
15443     58/pop-to-eax
15444     # . epilogue
15445     89/<- %esp 5/r32/ebp
15446     5d/pop-to-ebp
15447     c3/return
15448 
15449 $parse-mu-block:abort:
15450     # error("'{' or '}' should be on its own line, but got '")
15451     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
15452     (rewind-stream %ecx)
15453     (write-stream-data *(ebp+0x18) %ecx)
15454     (write-buffered *(ebp+0x18) "'\n")
15455     (flush *(ebp+0x18))
15456     (stop *(ebp+0x1c) 1)
15457     # never gets here
15458 
15459 new-block-name:  # fn: (addr function), out: (addr handle var)
15460     # . prologue
15461     55/push-ebp
15462     89/<- %ebp 4/r32/esp
15463     # . save registers
15464     50/push-eax
15465     51/push-ecx
15466     52/push-edx
15467     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
15468     8b/-> *(ebp+8) 0/r32/eax
15469     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15470     8b/-> *eax 0/r32/eax  # String-size
15471     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
15472     89/<- %ecx 0/r32/eax
15473     # var name/edx: (stream byte n)
15474     29/subtract-from %esp 1/r32/ecx
15475     ff 6/subop/push %ecx
15476     68/push 0/imm32/read
15477     68/push 0/imm32/write
15478     89/<- %edx 4/r32/esp
15479     (clear-stream %edx)
15480     # eax = fn->name
15481     8b/-> *(ebp+8) 0/r32/eax
15482     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15483     # construct result using Next-block-index (and increment it)
15484     (write %edx "$")
15485     (write %edx %eax)
15486     (write %edx ":")
15487     (write-int32-hex %edx *Next-block-index)
15488     ff 0/subop/increment *Next-block-index
15489     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
15490     # . eax = name->write
15491     8b/-> *edx 0/r32/eax
15492     # . edx = name->data
15493     8d/copy-address *(edx+0xc) 2/r32/edx
15494     # . eax = name->write + name->data
15495     01/add-to %eax 2/r32/edx
15496     # . push {edx, eax}
15497     ff 6/subop/push %eax
15498     ff 6/subop/push %edx
15499     89/<- %eax 4/r32/esp
15500     # out = new literal(s)
15501     (new-literal Heap %eax *(ebp+0xc))
15502 #?     8b/-> *(ebp+0xc) 0/r32/eax
15503 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
15504 #?     (write-int32-hex-buffered Stderr *(eax+8))
15505 #?     (write-buffered Stderr " for var ")
15506 #?     (write-int32-hex-buffered Stderr %eax)
15507 #?     (write-buffered Stderr Newline)
15508 #?     (flush Stderr)
15509 $new-block-name:end:
15510     # . reclaim locals
15511     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
15512     81 0/subop/add %ecx 8/imm32  # slice
15513     01/add-to %esp 1/r32/ecx
15514     # . restore registers
15515     5a/pop-to-edx
15516     59/pop-to-ecx
15517     58/pop-to-eax
15518     # . epilogue
15519     89/<- %esp 5/r32/ebp
15520     5d/pop-to-ebp
15521     c3/return
15522 
15523 check-no-tokens-left:  # line: (addr stream byte)
15524     # . prologue
15525     55/push-ebp
15526     89/<- %ebp 4/r32/esp
15527     # . save registers
15528     50/push-eax
15529     51/push-ecx
15530     # var s/ecx: slice
15531     68/push 0/imm32/end
15532     68/push 0/imm32/start
15533     89/<- %ecx 4/r32/esp
15534     #
15535     (next-mu-token *(ebp+8) %ecx)
15536     # if slice-empty?(s) return
15537     (slice-empty? %ecx)
15538     3d/compare-eax-and 0/imm32/false
15539     75/jump-if-!= $check-no-tokens-left:end/disp8
15540     # if (slice-starts-with?(s, '#') return
15541     # . eax = *s->start
15542     8b/-> *edx 0/r32/eax
15543     8a/copy-byte *eax 0/r32/AL
15544     81 4/subop/and %eax 0xff/imm32
15545     # . if (eax == '#') continue
15546     3d/compare-eax-and 0x23/imm32/hash
15547     74/jump-if-= $check-no-tokens-left:end/disp8
15548     # abort
15549     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
15550     (rewind-stream %ecx)
15551     (write-stream 2 %ecx)
15552     (write-buffered Stderr "'\n")
15553     (flush Stderr)
15554     # . syscall(exit, 1)
15555     bb/copy-to-ebx  1/imm32
15556     e8/call syscall_exit/disp32
15557     # never gets here
15558 $check-no-tokens-left:end:
15559     # . reclaim locals
15560     81 0/subop/add %esp 8/imm32
15561     # . restore registers
15562     59/pop-to-ecx
15563     58/pop-to-eax
15564     # . epilogue
15565     89/<- %esp 5/r32/ebp
15566     5d/pop-to-ebp
15567     c3/return
15568 
15569 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)
15570     # pseudocode:
15571     #   var v: (handle var)
15572     #   new-literal(name, v)
15573     #   push(vars, {v, false})
15574     #   parse-mu-block(in, vars, fn, out)
15575     #   pop(vars)
15576     #   out->tag = block
15577     #   out->var = v
15578     #
15579     # . prologue
15580     55/push-ebp
15581     89/<- %ebp 4/r32/esp
15582     # . save registers
15583     50/push-eax
15584     51/push-ecx
15585     57/push-edi
15586     # var v/ecx: (handle var)
15587     68/push 0/imm32
15588     68/push 0/imm32
15589     89/<- %ecx 4/r32/esp
15590     #
15591     (new-literal Heap *(ebp+8) %ecx)
15592     # push(vars, v)
15593     (push *(ebp+0x10) *ecx)
15594     (push *(ebp+0x10) *(ecx+4))
15595     (push *(ebp+0x10) 0)  # false
15596     #
15597     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
15598     # pop v off vars
15599     (pop *(ebp+0x10))  # => eax
15600     (pop *(ebp+0x10))  # => eax
15601     (pop *(ebp+0x10))  # => eax
15602     # var out-addr/edi: (addr stmt) = lookup(*out)
15603     8b/-> *(ebp+0x18) 7/r32/edi
15604     (lookup *edi *(edi+4))  # => eax
15605     89/<- %edi 0/r32/eax
15606     # out-addr->tag = named-block
15607     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
15608     # out-addr->var = v
15609     8b/-> *ecx 0/r32/eax
15610     89/<- *(edi+0xc) 0/r32/eax  # Block-var
15611     8b/-> *(ecx+4) 0/r32/eax
15612     89/<- *(edi+0x10) 0/r32/eax  # Block-var
15613 $parse-mu-named-block:end:
15614     # . reclaim locals
15615     81 0/subop/add %esp 8/imm32
15616     # . restore registers
15617     5f/pop-to-edi
15618     59/pop-to-ecx
15619     58/pop-to-eax
15620     # . epilogue
15621     89/<- %esp 5/r32/ebp
15622     5d/pop-to-ebp
15623     c3/return
15624 
15625 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)
15626     # . prologue
15627     55/push-ebp
15628     89/<- %ebp 4/r32/esp
15629     # . save registers
15630     50/push-eax
15631     51/push-ecx
15632     52/push-edx
15633     53/push-ebx
15634     57/push-edi
15635     # edi = out
15636     8b/-> *(ebp+0x10) 7/r32/edi
15637     # var word-slice/ecx: slice
15638     68/push 0/imm32/end
15639     68/push 0/imm32/start
15640     89/<- %ecx 4/r32/esp
15641     # var v/edx: (handle var)
15642     68/push 0/imm32
15643     68/push 0/imm32
15644     89/<- %edx 4/r32/esp
15645     # v = parse-var-with-type(next-mu-token(line))
15646     (next-mu-token *(ebp+8) %ecx)
15647     (parse-var-with-type %ecx *(ebp+8) %edx *(ebp+0x18) *(ebp+0x1c))
15648     # var v-addr/eax: (addr var)
15649     (lookup *edx *(edx+4))  # => eax
15650     # v->block-depth = *Curr-block-depth
15651     8b/-> *Curr-block-depth 3/r32/ebx
15652     89/<- *(eax+0x10) 3/r32/ebx  # Var-block-depth
15653     # either v has no register and there's no more to this line
15654     8b/-> *(eax+0x18) 0/r32/eax  # Var-register
15655     3d/compare-eax-and 0/imm32
15656     {
15657       75/jump-if-!= break/disp8
15658       # TODO: disallow vars of type 'byte' on the stack
15659       # ensure that there's nothing else on this line
15660       (next-mu-token *(ebp+8) %ecx)
15661       (slice-empty? %ecx)  # => eax
15662       3d/compare-eax-and 0/imm32/false
15663       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
15664       #
15665       (new-var-def Heap  *edx *(edx+4)  %edi)
15666       e9/jump $parse-mu-var-def:update-vars/disp32
15667     }
15668     # or v has a register and there's more to this line
15669     {
15670       0f 84/jump-if-= break/disp32
15671       # TODO: disallow vars of type 'byte' in registers 'esi' or 'edi'
15672       # TODO: vars of type 'byte' should only be initialized by clearing to 0
15673       # ensure that the next word is '<-'
15674       (next-mu-token *(ebp+8) %ecx)
15675       (slice-equal? %ecx "<-")  # => eax
15676       3d/compare-eax-and 0/imm32/false
15677       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
15678       #
15679       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
15680       (lookup *edi *(edi+4))  # => eax
15681       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
15682     }
15683 $parse-mu-var-def:update-vars:
15684     # push 'v' at end of function
15685     (push *(ebp+0xc) *edx)
15686     (push *(ebp+0xc) *(edx+4))
15687     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
15688 $parse-mu-var-def:end:
15689     # . reclaim locals
15690     81 0/subop/add %esp 0x10/imm32
15691     # . restore registers
15692     5f/pop-to-edi
15693     5b/pop-to-ebx
15694     5a/pop-to-edx
15695     59/pop-to-ecx
15696     58/pop-to-eax
15697     # . epilogue
15698     89/<- %esp 5/r32/ebp
15699     5d/pop-to-ebp
15700     c3/return
15701 
15702 $parse-mu-var-def:error1:
15703     (rewind-stream *(ebp+8))
15704     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
15705     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
15706     (flush *(ebp+0x18))
15707     (write-stream-data *(ebp+0x18) *(ebp+8))
15708     (write-buffered *(ebp+0x18) "'\n")
15709     (flush *(ebp+0x18))
15710     (stop *(ebp+0x1c) 1)
15711     # never gets here
15712 
15713 $parse-mu-var-def:error2:
15714     (rewind-stream *(ebp+8))
15715     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
15716     (write-buffered *(ebp+0x18) "fn ")
15717     8b/-> *(ebp+0x14) 0/r32/eax
15718     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15719     (write-buffered *(ebp+0x18) %eax)
15720     (write-buffered *(ebp+0x18) ": var ")
15721     # var v-addr/eax: (addr var) = lookup(v)
15722     (lookup *edx *(edx+4))  # => eax
15723     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15724     (write-buffered *(ebp+0x18) %eax)
15725     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
15726     (flush *(ebp+0x18))
15727     (stop *(ebp+0x1c) 1)
15728     # never gets here
15729 
15730 test-parse-mu-var-def:
15731     # 'var n: int'
15732     # . prologue
15733     55/push-ebp
15734     89/<- %ebp 4/r32/esp
15735     # setup
15736     8b/-> *Primitive-type-ids 0/r32/eax
15737     89/<- *Type-id 0/r32/eax  # stream-write
15738     (clear-stream _test-input-stream)
15739     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
15740     c7 0/subop/copy *Curr-block-depth 1/imm32
15741     # var out/esi: (handle stmt)
15742     68/push 0/imm32
15743     68/push 0/imm32
15744     89/<- %esi 4/r32/esp
15745     # var vars/ecx: (stack (addr var) 16)
15746     81 5/subop/subtract %esp 0xc0/imm32
15747     68/push 0xc0/imm32/size
15748     68/push 0/imm32/top
15749     89/<- %ecx 4/r32/esp
15750     (clear-stack %ecx)
15751     # convert
15752     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
15753     # var out-addr/esi: (addr stmt)
15754     (lookup *esi *(esi+4))  # => eax
15755     89/<- %esi 0/r32/eax
15756     #
15757     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
15758     # var v/ecx: (addr var) = lookup(out->var)
15759     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
15760     89/<- %ecx 0/r32/eax
15761     # v->name
15762     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
15763     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
15764     # v->register
15765     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
15766     # v->block-depth
15767     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
15768     # v->type == int
15769     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
15770     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
15771     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
15772     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
15773     # . epilogue
15774     89/<- %esp 5/r32/ebp
15775     5d/pop-to-ebp
15776     c3/return
15777 
15778 test-parse-mu-reg-var-def:
15779     # 'var n/eax: int <- copy 0'
15780     # . prologue
15781     55/push-ebp
15782     89/<- %ebp 4/r32/esp
15783     # setup
15784     8b/-> *Primitive-type-ids 0/r32/eax
15785     89/<- *Type-id 0/r32/eax  # stream-write
15786     (clear-stream _test-input-stream)
15787     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
15788     c7 0/subop/copy *Curr-block-depth 1/imm32
15789     # var out/esi: (handle stmt)
15790     68/push 0/imm32
15791     68/push 0/imm32
15792     89/<- %esi 4/r32/esp
15793     # var vars/ecx: (stack (addr var) 16)
15794     81 5/subop/subtract %esp 0xc0/imm32
15795     68/push 0xc0/imm32/size
15796     68/push 0/imm32/top
15797     89/<- %ecx 4/r32/esp
15798     (clear-stack %ecx)
15799     # convert
15800     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
15801     # var out-addr/esi: (addr stmt)
15802     (lookup *esi *(esi+4))  # => eax
15803     89/<- %esi 0/r32/eax
15804     #
15805     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
15806     # var v/ecx: (addr var) = lookup(out->outputs->value)
15807     # . eax: (addr stmt-var) = lookup(out->outputs)
15808     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
15809     # .
15810     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
15811     # . eax: (addr var) = lookup(eax->value)
15812     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15813     # . ecx = eax
15814     89/<- %ecx 0/r32/eax
15815     # v->name
15816     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
15817     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
15818     # v->register
15819     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
15820     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
15821     # v->block-depth
15822     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
15823     # v->type == int
15824     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
15825     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
15826     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
15827     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
15828     # . epilogue
15829     89/<- %esp 5/r32/ebp
15830     5d/pop-to-ebp
15831     c3/return
15832 
15833 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)
15834     # pseudocode:
15835     #   var name: slice
15836     #   allocate(Heap, Stmt-size, out)
15837     #   var out-addr: (addr stmt) = lookup(*out)
15838     #   out-addr->tag = stmt
15839     #   if stmt-has-outputs?(line)
15840     #     while true
15841     #       name = next-mu-token(line)
15842     #       if (name == '<-') break
15843     #       assert(is-identifier?(name))
15844     #       var v: (handle var) = lookup-var(name, vars)
15845     #       out-addr->outputs = append(v, out-addr->outputs)
15846     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
15847     #
15848     # . prologue
15849     55/push-ebp
15850     89/<- %ebp 4/r32/esp
15851     # . save registers
15852     50/push-eax
15853     51/push-ecx
15854     52/push-edx
15855     53/push-ebx
15856     57/push-edi
15857     # var name/ecx: slice
15858     68/push 0/imm32/end
15859     68/push 0/imm32/start
15860     89/<- %ecx 4/r32/esp
15861     # var is-deref?/edx: boolean = false
15862     ba/copy-to-edx 0/imm32/false
15863     # var v: (handle var)
15864     68/push 0/imm32
15865     68/push 0/imm32
15866     89/<- %ebx 4/r32/esp
15867     #
15868     (allocate Heap *Stmt-size *(ebp+0x14))
15869     # var out-addr/edi: (addr stmt) = lookup(*out)
15870     8b/-> *(ebp+0x14) 7/r32/edi
15871     (lookup *edi *(edi+4))  # => eax
15872     89/<- %edi 0/r32/eax
15873     # out-addr->tag = 1/stmt
15874     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
15875     {
15876       (stmt-has-outputs? *(ebp+8))
15877       3d/compare-eax-and 0/imm32/false
15878       0f 84/jump-if-= break/disp32
15879       {
15880 $parse-mu-stmt:read-outputs:
15881         # name = next-mu-token(line)
15882         (next-mu-token *(ebp+8) %ecx)
15883         # if slice-empty?(word-slice) break
15884         (slice-empty? %ecx)  # => eax
15885         3d/compare-eax-and 0/imm32/false
15886         0f 85/jump-if-!= break/disp32
15887         # if (name == "<-") break
15888         (slice-equal? %ecx "<-")  # => eax
15889         3d/compare-eax-and 0/imm32/false
15890         0f 85/jump-if-!= break/disp32
15891         # is-deref? = false
15892         ba/copy-to-edx 0/imm32/false
15893         # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
15894         8b/-> *ecx 0/r32/eax  # Slice-start
15895         8a/copy-byte *eax 0/r32/AL
15896         81 4/subop/and %eax 0xff/imm32
15897         3d/compare-eax-and 0x2a/imm32/asterisk
15898         {
15899           75/jump-if-!= break/disp8
15900           ff 0/subop/increment *ecx
15901           ba/copy-to-edx 1/imm32/true
15902         }
15903         # assert(is-identifier?(name))
15904         (is-identifier? %ecx)  # => eax
15905         3d/compare-eax-and 0/imm32/false
15906         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
15907         #
15908         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
15909         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
15910         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  %edx  %eax)  # Stmt1-outputs
15911         #
15912         e9/jump loop/disp32
15913       }
15914     }
15915     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
15916 $parse-mu-stmt:end:
15917     # . reclaim locals
15918     81 0/subop/add %esp 0x10/imm32
15919     # . restore registers
15920     5f/pop-to-edi
15921     5b/pop-to-ebx
15922     5a/pop-to-edx
15923     59/pop-to-ecx
15924     58/pop-to-eax
15925     # . epilogue
15926     89/<- %esp 5/r32/ebp
15927     5d/pop-to-ebp
15928     c3/return
15929 
15930 $parse-mu-stmt:abort:
15931     # error("invalid identifier '" name "'\n")
15932     (write-buffered *(ebp+0x18) "invalid identifier '")
15933     (write-slice-buffered *(ebp+0x18) %ecx)
15934     (write-buffered *(ebp+0x18) "'\n")
15935     (flush *(ebp+0x18))
15936     (stop *(ebp+0x1c) 1)
15937     # never gets here
15938 
15939 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)
15940     # pseudocode:
15941     #   stmt->name = slice-to-string(next-mu-token(line))
15942     #   while true
15943     #     name = next-mu-token(line)
15944     #     v = lookup-var-or-literal(name)
15945     #     stmt->inouts = append(v, stmt->inouts)
15946     #
15947     # . prologue
15948     55/push-ebp
15949     89/<- %ebp 4/r32/esp
15950     # . save registers
15951     50/push-eax
15952     51/push-ecx
15953     52/push-edx
15954     53/push-ebx
15955     56/push-esi
15956     57/push-edi
15957     # edi = stmt
15958     8b/-> *(ebp+8) 7/r32/edi
15959     # var name/ecx: slice
15960     68/push 0/imm32/end
15961     68/push 0/imm32/start
15962     89/<- %ecx 4/r32/esp
15963     # var is-deref?/edx: boolean = false
15964     ba/copy-to-edx 0/imm32/false
15965     # var v/esi: (handle var)
15966     68/push 0/imm32
15967     68/push 0/imm32
15968     89/<- %esi 4/r32/esp
15969 $add-operation-and-inputs-to-stmt:read-operation:
15970     (next-mu-token *(ebp+0xc) %ecx)
15971     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
15972     (slice-to-string Heap %ecx %eax)
15973     # var is-get?/ebx: boolean = (name == "get")
15974     (slice-equal? %ecx "get")  # => eax
15975     89/<- %ebx 0/r32/eax
15976     {
15977 $add-operation-and-inputs-to-stmt:read-inouts:
15978       # name = next-mu-token(line)
15979       (next-mu-token *(ebp+0xc) %ecx)
15980       # if slice-empty?(word-slice) break
15981       (slice-empty? %ecx)  # => eax
15982       3d/compare-eax-and 0/imm32/false
15983       0f 85/jump-if-!= break/disp32
15984       # if (name == "<-") abort
15985       (slice-equal? %ecx "<-")
15986       3d/compare-eax-and 0/imm32/false
15987       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
15988       # if (is-get? && second operand) lookup or create offset
15989       {
15990         81 7/subop/compare %ebx 0/imm32/false
15991         74/jump-if-= break/disp8
15992         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
15993         3d/compare-eax-and 0/imm32
15994         74/jump-if-= break/disp8
15995         (lookup-or-create-constant %eax %ecx %esi)
15996 #?         (lookup *esi *(esi+4))
15997 #?         (write-buffered Stderr "creating new output var ")
15998 #?         (write-int32-hex-buffered Stderr %eax)
15999 #?         (write-buffered Stderr " for field called ")
16000 #?         (write-slice-buffered Stderr %ecx)
16001 #?         (write-buffered Stderr "; var name ")
16002 #?         (lookup *eax *(eax+4))  # Var-name
16003 #?         (write-buffered Stderr %eax)
16004 #?         (write-buffered Stderr Newline)
16005 #?         (flush Stderr)
16006         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
16007       }
16008       # is-deref? = false
16009       ba/copy-to-edx 0/imm32/false
16010       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
16011       8b/-> *ecx 0/r32/eax  # Slice-start
16012       8a/copy-byte *eax 0/r32/AL
16013       81 4/subop/and %eax 0xff/imm32
16014       3d/compare-eax-and 0x2a/imm32/asterisk
16015       {
16016         75/jump-if-!= break/disp8
16017 $add-operation-and-inputs-to-stmt:inout-is-deref:
16018         ff 0/subop/increment *ecx
16019         ba/copy-to-edx 1/imm32/true
16020       }
16021       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16022 $add-operation-and-inputs-to-stmt:save-var:
16023       8d/copy-address *(edi+0xc) 0/r32/eax
16024       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
16025       #
16026       e9/jump loop/disp32
16027     }
16028 $add-operation-and-inputs-to-stmt:end:
16029     # . reclaim locals
16030     81 0/subop/add %esp 0x10/imm32
16031     # . restore registers
16032     5f/pop-to-edi
16033     5e/pop-to-esi
16034     5b/pop-to-ebx
16035     5a/pop-to-edx
16036     59/pop-to-ecx
16037     58/pop-to-eax
16038     # . epilogue
16039     89/<- %esp 5/r32/ebp
16040     5d/pop-to-ebp
16041     c3/return
16042 
16043 $add-operation-and-inputs-to-stmt:abort:
16044     # error("fn ___: invalid identifier in '" line "'\n")
16045     (write-buffered *(ebp+0x18) "fn ")
16046     8b/-> *(ebp+0x14) 0/r32/eax
16047     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16048     (write-buffered *(ebp+0x18) %eax)
16049     (rewind-stream *(ebp+0xc))
16050     (write-buffered *(ebp+0x18) ": invalid identifier in '")
16051     (write-stream-data *(ebp+0x18) *(ebp+0xc))
16052     (write-buffered *(ebp+0x18) "'\n")
16053     (flush *(ebp+0x18))
16054     (stop *(ebp+0x1c) 1)
16055     # never gets here
16056 
16057 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
16058     # . prologue
16059     55/push-ebp
16060     89/<- %ebp 4/r32/esp
16061     # . save registers
16062     51/push-ecx
16063     # var word-slice/ecx: slice
16064     68/push 0/imm32/end
16065     68/push 0/imm32/start
16066     89/<- %ecx 4/r32/esp
16067     # result = false
16068     b8/copy-to-eax 0/imm32/false
16069     (rewind-stream *(ebp+8))
16070     {
16071       (next-mu-token *(ebp+8) %ecx)
16072       # if slice-empty?(word-slice) break
16073       (slice-empty? %ecx)
16074       3d/compare-eax-and 0/imm32/false
16075       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
16076       0f 85/jump-if-!= break/disp32
16077       # if slice-starts-with?(word-slice, '#') break
16078       # . eax = *word-slice->start
16079       8b/-> *ecx 0/r32/eax
16080       8a/copy-byte *eax 0/r32/AL
16081       81 4/subop/and %eax 0xff/imm32
16082       # . if (eax == '#') break
16083       3d/compare-eax-and 0x23/imm32/hash
16084       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
16085       0f 84/jump-if-= break/disp32
16086       # if slice-equal?(word-slice, '<-') return true
16087       (slice-equal? %ecx "<-")
16088       3d/compare-eax-and 0/imm32/false
16089       74/jump-if-= loop/disp8
16090       b8/copy-to-eax 1/imm32/true
16091     }
16092 $stmt-has-outputs:end:
16093     (rewind-stream *(ebp+8))
16094     # . reclaim locals
16095     81 0/subop/add %esp 8/imm32
16096     # . restore registers
16097     59/pop-to-ecx
16098     # . epilogue
16099     89/<- %esp 5/r32/ebp
16100     5d/pop-to-ebp
16101     c3/return
16102 
16103 # if 'name' starts with a digit, create a new literal var for it
16104 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
16105 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)
16106     # . prologue
16107     55/push-ebp
16108     89/<- %ebp 4/r32/esp
16109     # . save registers
16110     50/push-eax
16111     51/push-ecx
16112     56/push-esi
16113     # esi = name
16114     8b/-> *(ebp+8) 6/r32/esi
16115     # if slice-empty?(name) abort
16116     (slice-empty? %esi)  # => eax
16117     3d/compare-eax-and 0/imm32/false
16118     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
16119     # var c/ecx: byte = *name->start
16120     8b/-> *esi 1/r32/ecx
16121     8a/copy-byte *ecx 1/r32/CL
16122     81 4/subop/and %ecx 0xff/imm32
16123     # if (is-decimal-digit?(c) || c == '-') return new var(name)
16124     {
16125       81 7/subop/compare %ecx 0x2d/imm32/dash
16126       74/jump-if-= $lookup-var-or-literal:literal/disp8
16127       (is-decimal-digit? %ecx)  # => eax
16128       3d/compare-eax-and 0/imm32/false
16129       74/jump-if-= break/disp8
16130 $lookup-var-or-literal:literal:
16131       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16132       eb/jump $lookup-var-or-literal:end/disp8
16133     }
16134     # else if (c == '"') return new var(name)
16135     {
16136       81 7/subop/compare %ecx 0x22/imm32/dquote
16137       75/jump-if-!= break/disp8
16138 $lookup-var-or-literal:literal-string:
16139       (new-literal Heap %esi *(ebp+0x10))
16140       eb/jump $lookup-var-or-literal:end/disp8
16141     }
16142     # otherwise return lookup-var(name, vars)
16143     {
16144 $lookup-var-or-literal:var:
16145       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16146     }
16147 $lookup-var-or-literal:end:
16148     # . restore registers
16149     5e/pop-to-esi
16150     59/pop-to-ecx
16151     58/pop-to-eax
16152     # . epilogue
16153     89/<- %esp 5/r32/ebp
16154     5d/pop-to-ebp
16155     c3/return
16156 
16157 $lookup-var-or-literal:abort:
16158     (write-buffered *(ebp+0x18) "fn ")
16159     8b/-> *(ebp+0x14) 0/r32/eax
16160     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16161     (write-buffered *(ebp+0x18) %eax)
16162     (write-buffered *(ebp+0x18) ": empty variable!")
16163     (flush *(ebp+0x18))
16164     (stop *(ebp+0x1c) 1)
16165     # never gets here
16166 
16167 # return first 'name' from the top (back) of 'vars' and abort if not found
16168 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)
16169     # . prologue
16170     55/push-ebp
16171     89/<- %ebp 4/r32/esp
16172     # . save registers
16173     50/push-eax
16174     #
16175     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16176     # if (*out == 0) abort
16177     8b/-> *(ebp+0x10) 0/r32/eax
16178     81 7/subop/compare *eax 0/imm32
16179     74/jump-if-= $lookup-var:abort/disp8
16180 $lookup-var:end:
16181     # . restore registers
16182     58/pop-to-eax
16183     # . epilogue
16184     89/<- %esp 5/r32/ebp
16185     5d/pop-to-ebp
16186     c3/return
16187 
16188 $lookup-var:abort:
16189     (write-buffered *(ebp+0x18) "fn ")
16190     8b/-> *(ebp+0x14) 0/r32/eax
16191     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16192     (write-buffered *(ebp+0x18) %eax)
16193     (write-buffered *(ebp+0x18) ": unknown variable '")
16194     (write-slice-buffered *(ebp+0x18) *(ebp+8))
16195     (write-buffered *(ebp+0x18) "'\n")
16196     (flush *(ebp+0x18))
16197     (stop *(ebp+0x1c) 1)
16198     # never gets here
16199 
16200 # return first 'name' from the top (back) of 'vars', and 0/null if not found
16201 # ensure that 'name' if in a register is the topmost variable in that register
16202 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)
16203     # pseudocode:
16204     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
16205     #   var min = vars->data
16206     #   while curr >= min
16207     #     var v: (handle var) = *curr
16208     #     if v->name == name
16209     #       return
16210     #     curr -= 12
16211     #
16212     # . prologue
16213     55/push-ebp
16214     89/<- %ebp 4/r32/esp
16215     # . save registers
16216     50/push-eax
16217     51/push-ecx
16218     52/push-edx
16219     53/push-ebx
16220     56/push-esi
16221     57/push-edi
16222     # clear out
16223     (zero-out *(ebp+0x10) *Handle-size)
16224     # esi = vars
16225     8b/-> *(ebp+0xc) 6/r32/esi
16226     # ebx = vars->top
16227     8b/-> *esi 3/r32/ebx
16228     # if (vars->top > vars->size) abort
16229     3b/compare<- *(esi+4) 0/r32/eax
16230     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
16231     # var min/edx: (addr handle var) = vars->data
16232     8d/copy-address *(esi+8) 2/r32/edx
16233     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
16234     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
16235     # var var-in-reg/edi: 16 addrs
16236     68/push 0/imm32
16237     68/push 0/imm32
16238     68/push 0/imm32
16239     68/push 0/imm32
16240     68/push 0/imm32
16241     68/push 0/imm32
16242     68/push 0/imm32
16243     68/push 0/imm32
16244     68/push 0/imm32
16245     68/push 0/imm32
16246     68/push 0/imm32
16247     68/push 0/imm32
16248     68/push 0/imm32
16249     68/push 0/imm32
16250     68/push 0/imm32
16251     68/push 0/imm32
16252     89/<- %edi 4/r32/esp
16253     {
16254 $lookup-var-helper:loop:
16255       # if (curr < min) return
16256       39/compare %ebx 2/r32/edx
16257       0f 82/jump-if-addr< break/disp32
16258       # var v/ecx: (addr var) = lookup(*curr)
16259       (lookup *ebx *(ebx+4))  # => eax
16260       89/<- %ecx 0/r32/eax
16261       # var vn/eax: (addr array byte) = lookup(v->name)
16262       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16263       # if (vn == name) return curr
16264       (slice-equal? *(ebp+8) %eax)  # => eax
16265       3d/compare-eax-and 0/imm32/false
16266       {
16267         74/jump-if-= break/disp8
16268 $lookup-var-helper:found:
16269         # var vr/eax: (addr array byte) = lookup(v->register)
16270         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
16271         3d/compare-eax-and 0/imm32
16272         {
16273           74/jump-if-= break/disp8
16274 $lookup-var-helper:found-register:
16275           # var reg/eax: int = get(Registers, vr)
16276           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
16277           8b/-> *eax 0/r32/eax
16278           # if (var-in-reg[reg]) error
16279           8b/-> *(edi+eax<<2) 0/r32/eax
16280           3d/compare-eax-and 0/imm32
16281           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
16282         }
16283 $lookup-var-helper:return:
16284         # esi = out
16285         8b/-> *(ebp+0x10) 6/r32/esi
16286         # *out = *curr
16287         8b/-> *ebx 0/r32/eax
16288         89/<- *esi 0/r32/eax
16289         8b/-> *(ebx+4) 0/r32/eax
16290         89/<- *(esi+4) 0/r32/eax
16291         # return
16292         eb/jump $lookup-var-helper:end/disp8
16293       }
16294       # 'name' not yet found; update var-in-reg if v in register
16295       # . var vr/eax: (addr array byte) = lookup(v->register)
16296       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
16297       # . if (vr == 0) continue
16298       3d/compare-eax-and 0/imm32
16299       74/jump-if-= $lookup-var-helper:continue/disp8
16300       # . var reg/eax: int = get(Registers, vr)
16301       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
16302       8b/-> *eax 0/r32/eax
16303       # . var-in-reg[reg] = v
16304       89/<- *(edi+eax<<2) 1/r32/ecx
16305 $lookup-var-helper:continue:
16306       # curr -= 12
16307       81 5/subop/subtract %ebx 0xc/imm32
16308       e9/jump loop/disp32
16309     }
16310 $lookup-var-helper:end:
16311     # . reclaim locals
16312     81 0/subop/add %esp 0x40/imm32
16313     # . restore registers
16314     5f/pop-to-edi
16315     5e/pop-to-esi
16316     5b/pop-to-ebx
16317     5a/pop-to-edx
16318     59/pop-to-ecx
16319     58/pop-to-eax
16320     # . epilogue
16321     89/<- %esp 5/r32/ebp
16322     5d/pop-to-ebp
16323     c3/return
16324 
16325 $lookup-var-helper:error1:
16326     (write-buffered *(ebp+0x18) "fn ")
16327     8b/-> *(ebp+0x14) 0/r32/eax
16328     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16329     (write-buffered *(ebp+0x18) %eax)
16330     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
16331     (write-slice-buffered *(ebp+0x18) *(ebp+8))
16332     (write-buffered *(ebp+0x18) "'\n")
16333     (flush *(ebp+0x18))
16334     (stop *(ebp+0x1c) 1)
16335     # never gets here
16336 
16337 $lookup-var-helper:error2:
16338     # eax contains the conflicting var at this point
16339     (write-buffered *(ebp+0x18) "fn ")
16340     50/push-eax
16341     8b/-> *(ebp+0x14) 0/r32/eax
16342     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16343     (write-buffered *(ebp+0x18) %eax)
16344     58/pop-eax
16345     (write-buffered *(ebp+0x18) ": register ")
16346     50/push-eax
16347     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16348     (write-buffered *(ebp+0x18) %eax)
16349     58/pop-to-eax
16350     (write-buffered *(ebp+0x18) " reads var '")
16351     (write-slice-buffered *(ebp+0x18) *(ebp+8))
16352     (write-buffered *(ebp+0x18) "' after writing var '")
16353     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16354     (write-buffered *(ebp+0x18) %eax)
16355     (write-buffered *(ebp+0x18) "'\n")
16356     (flush *(ebp+0x18))
16357     (stop *(ebp+0x1c) 1)
16358     # never gets here
16359 
16360 dump-vars:  # vars: (addr stack live-var)
16361     # pseudocode:
16362     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
16363     #   var min = vars->data
16364     #   while curr >= min
16365     #     var v: (handle var) = *curr
16366     #     print v
16367     #     curr -= 12
16368     #
16369     # . prologue
16370     55/push-ebp
16371     89/<- %ebp 4/r32/esp
16372     # . save registers
16373     52/push-edx
16374     53/push-ebx
16375     56/push-esi
16376     # esi = vars
16377     8b/-> *(ebp+8) 6/r32/esi
16378     # ebx = vars->top
16379     8b/-> *esi 3/r32/ebx
16380     # var min/edx: (addr handle var) = vars->data
16381     8d/copy-address *(esi+8) 2/r32/edx
16382     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
16383     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
16384     {
16385 $dump-vars:loop:
16386       # if (curr < min) return
16387       39/compare %ebx 2/r32/edx
16388       0f 82/jump-if-addr< break/disp32
16389       #
16390       (write-buffered Stderr "  var@")
16391       (dump-var 2 %ebx)
16392       # curr -= 12
16393       81 5/subop/subtract %ebx 0xc/imm32
16394       e9/jump loop/disp32
16395     }
16396 $dump-vars:end:
16397     # . restore registers
16398     5e/pop-to-esi
16399     5b/pop-to-ebx
16400     5a/pop-to-edx
16401     # . epilogue
16402     89/<- %esp 5/r32/ebp
16403     5d/pop-to-ebp
16404     c3/return
16405 
16406 == data
16407 # Like Registers, but no esp or ebp
16408 Mu-registers:  # (addr stream {(handle array byte), int})
16409   # a table is a stream
16410   0xa8/imm32/write
16411   0/imm32/read
16412   0xa8/imm32/length
16413   # data
16414   # general-purpose registers
16415   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
16416   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
16417   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
16418   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
16419   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
16420   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
16421   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
16422   # floating-point registers
16423   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
16424   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
16425   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
16426   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
16427   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
16428   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
16429   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
16430   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
16431 
16432 # Like Mu-registers, but with unique codes for integer and floating-point
16433 # registers.
16434 # Don't use this for code-generation, only for checking.
16435 Mu-registers-unique:  # (addr stream {(handle array byte), int})
16436   # a table is a stream
16437   0xa8/imm32/write
16438   0/imm32/read
16439   0xa8/imm32/length
16440   # data
16441   # general-purpose registers
16442   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
16443   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
16444   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
16445   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
16446   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
16447   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
16448   # floating-point registers
16449   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
16450   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
16451   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
16452   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
16453   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
16454   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
16455   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
16456   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
16457 
16458 $Mu-register-eax:
16459   0x11/imm32/alloc-id
16460   3/imm32/size
16461   0x65/e 0x61/a 0x78/x
16462 
16463 $Mu-register-ecx:
16464   0x11/imm32/alloc-id
16465   3/imm32/size
16466   0x65/e 0x63/c 0x78/x
16467 
16468 $Mu-register-edx:
16469   0x11/imm32/alloc-id
16470   3/imm32/size
16471   0x65/e 0x64/d 0x78/x
16472 
16473 $Mu-register-ebx:
16474   0x11/imm32/alloc-id
16475   3/imm32/size
16476   0x65/e 0x62/b 0x78/x
16477 
16478 $Mu-register-esi:
16479   0x11/imm32/alloc-id
16480   3/imm32/size
16481   0x65/e 0x73/s 0x69/i
16482 
16483 $Mu-register-edi:
16484   0x11/imm32/alloc-id
16485   3/imm32/size
16486   0x65/e 0x64/d 0x69/i
16487 
16488 $Mu-register-xmm0:
16489   0x11/imm32/alloc-id:fake:payload
16490   # "xmm0"
16491   0x4/imm32/size
16492   0x78/x 0x6d/m 0x6d/m 0x30/0
16493 
16494 $Mu-register-xmm1:
16495   0x11/imm32/alloc-id:fake:payload
16496   # "xmm1"
16497   0x4/imm32/size
16498   0x78/x 0x6d/m 0x6d/m 0x31/1
16499 
16500 $Mu-register-xmm2:
16501   0x11/imm32/alloc-id:fake:payload
16502   # "xmm2"
16503   0x4/imm32/size
16504   0x78/x 0x6d/m 0x6d/m 0x32/2
16505 
16506 $Mu-register-xmm3:
16507   0x11/imm32/alloc-id:fake:payload
16508   # "xmm3"
16509   0x4/imm32/size
16510   0x78/x 0x6d/m 0x6d/m 0x33/3
16511 
16512 $Mu-register-xmm4:
16513   0x11/imm32/alloc-id:fake:payload
16514   # "xmm4"
16515   0x4/imm32/size
16516   0x78/x 0x6d/m 0x6d/m 0x34/4
16517 
16518 $Mu-register-xmm5:
16519   0x11/imm32/alloc-id:fake:payload
16520   # "xmm5"
16521   0x4/imm32/size
16522   0x78/x 0x6d/m 0x6d/m 0x35/5
16523 
16524 $Mu-register-xmm6:
16525   0x11/imm32/alloc-id:fake:payload
16526   # "xmm6"
16527   0x4/imm32/size
16528   0x78/x 0x6d/m 0x6d/m 0x36/6
16529 
16530 $Mu-register-xmm7:
16531   0x11/imm32/alloc-id:fake:payload
16532   # "xmm7"
16533   0x4/imm32/size
16534   0x78/x 0x6d/m 0x6d/m 0x37/7
16535 
16536 == code
16537 
16538 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
16539 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
16540     # . prologue
16541     55/push-ebp
16542     89/<- %ebp 4/r32/esp
16543     # . save registers
16544     50/push-eax
16545     # var out-addr/eax: (addr var)
16546     (lookup *(ebp+8) *(ebp+0xc))  # => eax
16547     #
16548     (binding-exists? %eax *(ebp+0x10))  # => eax
16549     3d/compare-eax-and 0/imm32/false
16550     75/jump-if-!= $maybe-define-var:end/disp8
16551     # otherwise update vars
16552     (push *(ebp+0x10) *(ebp+8))
16553     (push *(ebp+0x10) *(ebp+0xc))
16554     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
16555 $maybe-define-var:end:
16556     # . restore registers
16557     58/pop-to-eax
16558     # . epilogue
16559     89/<- %esp 5/r32/ebp
16560     5d/pop-to-ebp
16561     c3/return
16562 
16563 # simpler version of lookup-var-helper
16564 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
16565     # pseudocode:
16566     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
16567     #   var min = vars->data
16568     #   while curr >= min
16569     #     var v: (handle var) = *curr
16570     #     if v->name == target->name
16571     #       return true
16572     #     curr -= 12
16573     #   return false
16574     #
16575     # . prologue
16576     55/push-ebp
16577     89/<- %ebp 4/r32/esp
16578     # . save registers
16579     51/push-ecx
16580     52/push-edx
16581     56/push-esi
16582     # var target-name/ecx: (addr array byte) = lookup(target->name)
16583     8b/-> *(ebp+8) 0/r32/eax
16584     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16585     89/<- %ecx 0/r32/eax
16586     # esi = vars
16587     8b/-> *(ebp+0xc) 6/r32/esi
16588     # eax = vars->top
16589     8b/-> *esi 0/r32/eax
16590     # var min/edx: (addr handle var) = vars->data
16591     8d/copy-address *(esi+8) 2/r32/edx
16592     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
16593     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
16594     {
16595 $binding-exists?:loop:
16596       # if (curr < min) return
16597       39/compare %esi 2/r32/edx
16598       0f 82/jump-if-addr< break/disp32
16599       # var v/eax: (addr var) = lookup(*curr)
16600       (lookup *esi *(esi+4))  # => eax
16601       # var vn/eax: (addr array byte) = lookup(v->name)
16602       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16603       # if (vn == target-name) return true
16604       (string-equal? %ecx %eax)  # => eax
16605       3d/compare-eax-and 0/imm32/false
16606       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
16607       # curr -= 12
16608       81 5/subop/subtract %esi 0xc/imm32
16609       e9/jump loop/disp32
16610     }
16611     b8/copy-to-eax 0/imm32/false
16612 $binding-exists?:end:
16613     # . restore registers
16614     5e/pop-to-esi
16615     5a/pop-to-edx
16616     59/pop-to-ecx
16617     # . epilogue
16618     89/<- %esp 5/r32/ebp
16619     5d/pop-to-ebp
16620     c3/return
16621 
16622 test-parse-mu-stmt:
16623     # . prologue
16624     55/push-ebp
16625     89/<- %ebp 4/r32/esp
16626     # setup
16627     8b/-> *Primitive-type-ids 0/r32/eax
16628     89/<- *Type-id 0/r32/eax  # stream-write
16629     (clear-stream _test-input-stream)
16630     (write _test-input-stream "increment n\n")
16631     # var vars/ecx: (stack (addr var) 16)
16632     81 5/subop/subtract %esp 0xc0/imm32
16633     68/push 0xc0/imm32/size
16634     68/push 0/imm32/top
16635     89/<- %ecx 4/r32/esp
16636     (clear-stack %ecx)
16637     # var v/edx: (handle var)
16638     68/push 0/imm32
16639     68/push 0/imm32
16640     89/<- %edx 4/r32/esp
16641     # var s/eax: (handle array byte)
16642     68/push 0/imm32
16643     68/push 0/imm32
16644     89/<- %eax 4/r32/esp
16645     # v = new var("n")
16646     (copy-array Heap "n" %eax)
16647     (new-var Heap *eax *(eax+4) %edx)
16648     #
16649     (push %ecx *edx)
16650     (push %ecx *(edx+4))
16651     (push %ecx 0)
16652     # var out/eax: (handle stmt)
16653     68/push 0/imm32
16654     68/push 0/imm32
16655     89/<- %eax 4/r32/esp
16656     # convert
16657     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
16658     # var out-addr/edx: (addr stmt) = lookup(*out)
16659     (lookup *eax *(eax+4))  # => eax
16660     89/<- %edx 0/r32/eax
16661     # out->tag
16662     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
16663     # out->operation
16664     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
16665     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
16666     # out->inouts->value->name
16667     # . eax = out->inouts
16668     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16669     # . eax = out->inouts->value
16670     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16671     # . eax = out->inouts->value->name
16672     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16673     # .
16674     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
16675     # . epilogue
16676     89/<- %esp 5/r32/ebp
16677     5d/pop-to-ebp
16678     c3/return
16679 
16680 test-parse-mu-stmt-with-comma:
16681     # . prologue
16682     55/push-ebp
16683     89/<- %ebp 4/r32/esp
16684     # setup
16685     8b/-> *Primitive-type-ids 0/r32/eax
16686     89/<- *Type-id 0/r32/eax  # stream-write
16687     (clear-stream _test-input-stream)
16688     (write _test-input-stream "copy-to n, 3\n")
16689     # var vars/ecx: (stack (addr var) 16)
16690     81 5/subop/subtract %esp 0xc0/imm32
16691     68/push 0xc0/imm32/size
16692     68/push 0/imm32/top
16693     89/<- %ecx 4/r32/esp
16694     (clear-stack %ecx)
16695     # var v/edx: (handle var)
16696     68/push 0/imm32
16697     68/push 0/imm32
16698     89/<- %edx 4/r32/esp
16699     # var s/eax: (handle array byte)
16700     68/push 0/imm32
16701     68/push 0/imm32
16702     89/<- %eax 4/r32/esp
16703     # v = new var("n")
16704     (copy-array Heap "n" %eax)
16705     (new-var Heap *eax *(eax+4) %edx)
16706     #
16707     (push %ecx *edx)
16708     (push %ecx *(edx+4))
16709     (push %ecx 0)
16710     # var out/eax: (handle stmt)
16711     68/push 0/imm32
16712     68/push 0/imm32
16713     89/<- %eax 4/r32/esp
16714     # convert
16715     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
16716     # var out-addr/edx: (addr stmt) = lookup(*out)
16717     (lookup *eax *(eax+4))  # => eax
16718     89/<- %edx 0/r32/eax
16719     # out->tag
16720     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
16721     # out->operation
16722     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
16723     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
16724     # out->inouts->value->name
16725     # . eax = out->inouts
16726     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16727     # . eax = out->inouts->value
16728     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16729     # . eax = out->inouts->value->name
16730     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16731     # .
16732     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
16733     # . epilogue
16734     89/<- %esp 5/r32/ebp
16735     5d/pop-to-ebp
16736     c3/return
16737 
16738 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
16739     # . prologue
16740     55/push-ebp
16741     89/<- %ebp 4/r32/esp
16742     # . save registers
16743     50/push-eax
16744     51/push-ecx
16745     # ecx = out
16746     8b/-> *(ebp+0x14) 1/r32/ecx
16747     #
16748     (allocate *(ebp+8) *Var-size %ecx)
16749     # var out-addr/eax: (addr var)
16750     (lookup *ecx *(ecx+4))  # => eax
16751     # out-addr->name = name
16752     8b/-> *(ebp+0xc) 1/r32/ecx
16753     89/<- *eax 1/r32/ecx  # Var-name
16754     8b/-> *(ebp+0x10) 1/r32/ecx
16755     89/<- *(eax+4) 1/r32/ecx  # Var-name
16756 #?     (write-buffered Stderr "var ")
16757 #?     (lookup *(ebp+0xc) *(ebp+0x10))
16758 #?     (write-buffered Stderr %eax)
16759 #?     (write-buffered Stderr " at ")
16760 #?     8b/-> *(ebp+0x14) 1/r32/ecx
16761 #?     (lookup *ecx *(ecx+4))  # => eax
16762 #?     (write-int32-hex-buffered Stderr %eax)
16763 #?     (write-buffered Stderr Newline)
16764 #?     (flush Stderr)
16765 $new-var:end:
16766     # . restore registers
16767     59/pop-to-ecx
16768     58/pop-to-eax
16769     # . epilogue
16770     89/<- %esp 5/r32/ebp
16771     5d/pop-to-ebp
16772     c3/return
16773 
16774 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)
16775     # . prologue
16776     55/push-ebp
16777     89/<- %ebp 4/r32/esp
16778     # . save registers
16779     50/push-eax
16780     51/push-ecx
16781     # if (!is-hex-int?(name)) abort
16782     (is-hex-int? *(ebp+0xc))  # => eax
16783     3d/compare-eax-and 0/imm32/false
16784     0f 84/jump-if-= $new-literal-integer:abort/disp32
16785     # a little more error-checking
16786     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
16787     # out = new var(s)
16788     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
16789     # var out-addr/ecx: (addr var) = lookup(*out)
16790     8b/-> *(ebp+0x10) 0/r32/eax
16791     (lookup *eax *(eax+4))  # => eax
16792     89/<- %ecx 0/r32/eax
16793     # out-addr->block-depth = *Curr-block-depth
16794     8b/-> *Curr-block-depth 0/r32/eax
16795     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
16796     # out-addr->type = new tree()
16797     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
16798     (allocate *(ebp+8) *Type-tree-size %eax)
16799     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16800     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
16801     # nothing else to do; default type is 'literal'
16802 $new-literal-integer:end:
16803     # . reclaim locals
16804     81 0/subop/add %esp 8/imm32
16805     # . restore registers
16806     59/pop-to-ecx
16807     58/pop-to-eax
16808     # . epilogue
16809     89/<- %esp 5/r32/ebp
16810     5d/pop-to-ebp
16811     c3/return
16812 
16813 $new-literal-integer:abort:
16814     (write-buffered *(ebp+0x18) "fn ")
16815     8b/-> *(ebp+0x14) 0/r32/eax
16816     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16817     (write-buffered *(ebp+0x18) %eax)
16818     (write-buffered *(ebp+0x18) ": variable '")
16819     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
16820     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
16821     (flush *(ebp+0x18))
16822     (stop *(ebp+0x1c) 1)
16823     # never gets here
16824 
16825 # precondition: name is a valid hex integer; require a '0x' prefix
16826 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
16827     # . prologue
16828     55/push-ebp
16829     89/<- %ebp 4/r32/esp
16830     # . save registers
16831     50/push-eax
16832     51/push-ecx
16833     52/push-edx
16834     # ecx = name
16835     8b/-> *(ebp+8) 1/r32/ecx
16836     # var start/edx: (addr byte) = name->start
16837     8b/-> *ecx 2/r32/edx
16838     # if (*start == '-') ++start
16839     b8/copy-to-eax 0/imm32
16840     8a/copy-byte *edx 0/r32/AL
16841     3d/compare-eax-and 0x2d/imm32/dash
16842     {
16843       75/jump-if-!= break/disp8
16844       42/increment-edx
16845     }
16846     # var end/ecx: (addr byte) = name->end
16847     8b/-> *(ecx+4) 1/r32/ecx
16848     # var len/eax: int = name->end - name->start
16849     89/<- %eax 1/r32/ecx
16850     29/subtract-from %eax 2/r32/edx
16851     # if (len <= 1) return
16852     3d/compare-eax-with 1/imm32
16853     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
16854 $check-mu-hex-int:length->-1:
16855     # if slice-starts-with?({start, end}, "0x") return
16856     # . var tmp = {start, end}
16857     51/push-ecx
16858     52/push-edx
16859     89/<- %eax 4/r32/esp
16860     # .
16861     (slice-starts-with? %eax "0x")  # => eax
16862     # . reclaim tmp
16863     81 0/subop/add %esp 8/imm32
16864     # .
16865     3d/compare-eax-with 0/imm32/false
16866     75/jump-if-!= $check-mu-hex-int:end/disp8
16867 $check-mu-hex-int:abort:
16868     # otherwise abort
16869     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
16870     (write-slice-buffered *(ebp+0xc) *(ebp+8))
16871     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
16872     (flush *(ebp+0xc))
16873     (stop *(ebp+0x10) 1)
16874 $check-mu-hex-int:end:
16875     # . restore registers
16876     5a/pop-to-edx
16877     59/pop-to-ecx
16878     58/pop-to-eax
16879     # . epilogue
16880     89/<- %esp 5/r32/ebp
16881     5d/pop-to-ebp
16882     c3/return
16883 
16884 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
16885     # . prologue
16886     55/push-ebp
16887     89/<- %ebp 4/r32/esp
16888     # . save registers
16889     50/push-eax
16890     51/push-ecx
16891     # var s/ecx: (handle array byte)
16892     68/push 0/imm32
16893     68/push 0/imm32
16894     89/<- %ecx 4/r32/esp
16895     # s = slice-to-string(name)
16896     (slice-to-string Heap *(ebp+0xc) %ecx)
16897     # allocate to out
16898     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
16899     # var out-addr/ecx: (addr var) = lookup(*out)
16900     8b/-> *(ebp+0x10) 1/r32/ecx
16901     (lookup *ecx *(ecx+4))  # => eax
16902     89/<- %ecx 0/r32/eax
16903     # out-addr->block-depth = *Curr-block-depth
16904     8b/-> *Curr-block-depth 0/r32/eax
16905     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
16906     # out-addr->type/eax = new type
16907     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
16908     (allocate *(ebp+8) *Type-tree-size %eax)
16909     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16910     # nothing else to do; default type is 'literal'
16911     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
16912 $new-literal:end:
16913     # . reclaim locals
16914     81 0/subop/add %esp 8/imm32
16915     # . restore registers
16916     59/pop-to-ecx
16917     58/pop-to-eax
16918     # . epilogue
16919     89/<- %esp 5/r32/ebp
16920     5d/pop-to-ebp
16921     c3/return
16922 
16923 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
16924     # . prologue
16925     55/push-ebp
16926     89/<- %ebp 4/r32/esp
16927     # . save registers
16928     51/push-ecx
16929     # var tmp/ecx: (handle array byte)
16930     68/push 0/imm32
16931     68/push 0/imm32
16932     89/<- %ecx 4/r32/esp
16933     # tmp = slice-to-string(name)
16934     (slice-to-string Heap *(ebp+0xc) %ecx)
16935     # out = new-var(tmp)
16936     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
16937 $new-var-from-slice:end:
16938     # . reclaim locals
16939     81 0/subop/add %esp 8/imm32
16940     # . restore registers
16941     59/pop-to-ecx
16942     # . epilogue
16943     89/<- %esp 5/r32/ebp
16944     5d/pop-to-ebp
16945     c3/return
16946 
16947 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
16948     # . prologue
16949     55/push-ebp
16950     89/<- %ebp 4/r32/esp
16951     # . save registers
16952     50/push-eax
16953     51/push-ecx
16954     #
16955     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
16956     # var out-addr/eax: (addr stmt) = lookup(*out)
16957     8b/-> *(ebp+0x14) 0/r32/eax
16958     (lookup *eax *(eax+4))  # => eax
16959     # out-addr->tag = stmt
16960     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
16961     # result->var = var
16962     8b/-> *(ebp+0xc) 1/r32/ecx
16963     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
16964     8b/-> *(ebp+0x10) 1/r32/ecx
16965     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
16966 $new-var-def:end:
16967     # . restore registers
16968     59/pop-to-ecx
16969     58/pop-to-eax
16970     # . epilogue
16971     89/<- %esp 5/r32/ebp
16972     5d/pop-to-ebp
16973     c3/return
16974 
16975 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
16976     # . prologue
16977     55/push-ebp
16978     89/<- %ebp 4/r32/esp
16979     # . save registers
16980     50/push-eax
16981     # eax = out
16982     8b/-> *(ebp+0x14) 0/r32/eax
16983     #
16984     (allocate *(ebp+8) *Stmt-size %eax)
16985     # var out-addr/eax: (addr stmt) = lookup(*out)
16986     (lookup *eax *(eax+4))  # => eax
16987     # set tag
16988     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
16989     # set output
16990     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
16991     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
16992 $new-reg-var-def:end:
16993     # . restore registers
16994     58/pop-to-eax
16995     # . epilogue
16996     89/<- %esp 5/r32/ebp
16997     5d/pop-to-ebp
16998     c3/return
16999 
17000 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
17001     # . prologue
17002     55/push-ebp
17003     89/<- %ebp 4/r32/esp
17004     # . save registers
17005     50/push-eax
17006     51/push-ecx
17007     57/push-edi
17008     # edi = out
17009     8b/-> *(ebp+0x1c) 7/r32/edi
17010     # *out = new list
17011     (allocate *(ebp+8) *List-size %edi)
17012     # var out-addr/edi: (addr list _type) = lookup(*out)
17013     (lookup *edi *(edi+4))  # => eax
17014     89/<- %edi 0/r32/eax
17015     # out-addr->value = value
17016     8b/-> *(ebp+0xc) 0/r32/eax
17017     89/<- *edi 0/r32/eax  # List-value
17018     8b/-> *(ebp+0x10) 0/r32/eax
17019     89/<- *(edi+4) 0/r32/eax  # List-value
17020     # if (list == null) return
17021     81 7/subop/compare *(ebp+0x14) 0/imm32
17022     74/jump-if-= $append-list:end/disp8
17023     # otherwise append
17024 $append-list:non-empty-list:
17025     # var curr/eax: (addr list _type) = lookup(list)
17026     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
17027     # while (curr->next != null) curr = curr->next
17028     {
17029       81 7/subop/compare *(eax+8) 0/imm32  # List-next
17030       74/jump-if-= break/disp8
17031       # curr = lookup(curr->next)
17032       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
17033       #
17034       eb/jump loop/disp8
17035     }
17036     # edi = out
17037     8b/-> *(ebp+0x1c) 7/r32/edi
17038     # curr->next = out
17039     8b/-> *edi 1/r32/ecx
17040     89/<- *(eax+8) 1/r32/ecx  # List-next
17041     8b/-> *(edi+4) 1/r32/ecx
17042     89/<- *(eax+0xc) 1/r32/ecx  # List-next
17043     # out = list
17044     8b/-> *(ebp+0x14) 1/r32/ecx
17045     89/<- *edi 1/r32/ecx
17046     8b/-> *(ebp+0x18) 1/r32/ecx
17047     89/<- *(edi+4) 1/r32/ecx
17048 $append-list:end:
17049     # . restore registers
17050     5f/pop-to-edi
17051     59/pop-to-ecx
17052     58/pop-to-eax
17053     # . epilogue
17054     89/<- %esp 5/r32/ebp
17055     5d/pop-to-ebp
17056     c3/return
17057 
17058 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
17059     # . prologue
17060     55/push-ebp
17061     89/<- %ebp 4/r32/esp
17062     # . save registers
17063     50/push-eax
17064     51/push-ecx
17065     57/push-edi
17066     # edi = out
17067     8b/-> *(ebp+0x20) 7/r32/edi
17068     # out = new stmt-var
17069     (allocate *(ebp+8) *Stmt-var-size %edi)
17070     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
17071     (lookup *edi *(edi+4))  # => eax
17072     89/<- %ecx 0/r32/eax
17073     # out-addr->value = v
17074     8b/-> *(ebp+0xc) 0/r32/eax
17075     89/<- *ecx 0/r32/eax  # Stmt-var-value
17076     8b/-> *(ebp+0x10) 0/r32/eax
17077     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
17078     # out-addr->is-deref? = is-deref?
17079     8b/-> *(ebp+0x1c) 0/r32/eax
17080     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
17081     # if (vars == null) return result
17082     81 7/subop/compare *(ebp+0x14) 0/imm32/null
17083     74/jump-if-= $append-stmt-var:end/disp8
17084     # otherwise append
17085     # var curr/eax: (addr stmt-var) = lookup(vars)
17086     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
17087     # while (curr->next != null) curr = curr->next
17088     {
17089       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
17090       74/jump-if-= break/disp8
17091       # curr = lookup(curr->next)
17092       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
17093       #
17094       eb/jump loop/disp8
17095     }
17096     # curr->next = out
17097     8b/-> *edi 1/r32/ecx
17098     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
17099     8b/-> *(edi+4) 1/r32/ecx
17100     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
17101     # out = vars
17102     8b/-> *(ebp+0x14) 1/r32/ecx
17103     89/<- *edi 1/r32/ecx
17104     8b/-> *(ebp+0x18) 1/r32/ecx
17105     89/<- *(edi+4) 1/r32/ecx
17106 $append-stmt-var:end:
17107     # . restore registers
17108     5f/pop-to-edi
17109     59/pop-to-ecx
17110     58/pop-to-eax
17111     # . epilogue
17112     89/<- %esp 5/r32/ebp
17113     5d/pop-to-ebp
17114     c3/return
17115 
17116 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
17117     # . prologue
17118     55/push-ebp
17119     89/<- %ebp 4/r32/esp
17120     # . save registers
17121     50/push-eax
17122     56/push-esi
17123     # esi = block
17124     8b/-> *(ebp+0xc) 6/r32/esi
17125     # block->stmts = append(x, block->stmts)
17126     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
17127     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
17128 $append-to-block:end:
17129     # . restore registers
17130     5e/pop-to-esi
17131     58/pop-to-eax
17132     # . epilogue
17133     89/<- %esp 5/r32/ebp
17134     5d/pop-to-ebp
17135     c3/return
17136 
17137 ## Parsing types
17138 # We need to create metadata on user-defined types, and we need to use this
17139 # metadata as we parse instructions.
17140 # However, we also want to allow types to be used before their definitions.
17141 # This means we can't ever assume any type data structures exist.
17142 
17143 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
17144     # . prologue
17145     55/push-ebp
17146     89/<- %ebp 4/r32/esp
17147     # . save registers
17148     50/push-eax
17149     56/push-esi
17150     # var container-type/esi: type-id
17151     (container-type *(ebp+8))  # => eax
17152     89/<- %esi 0/r32/eax
17153     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
17154     68/push 0/imm32
17155     68/push 0/imm32
17156     89/<- %eax 4/r32/esp
17157     (find-or-create-typeinfo %esi %eax)
17158     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
17159     (lookup *eax *(eax+4))  # => eax
17160     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
17161 #?     (write-buffered Stderr "constant: ")
17162 #?     (write-slice-buffered Stderr *(ebp+0xc))
17163 #?     (write-buffered Stderr Newline)
17164 #?     (flush Stderr)
17165     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
17166 #?     8b/-> *(ebp+0x10) 0/r32/eax
17167 #?     (write-buffered Stderr "@")
17168 #?     (lookup *eax *(eax+4))
17169 #?     (write-int32-hex-buffered Stderr %eax)
17170 #?     (lookup *eax *(eax+4))
17171 #?     (write-buffered Stderr %eax)
17172 #?     (write-buffered Stderr Newline)
17173 #?     (flush Stderr)
17174 #?     (write-buffered Stderr "offset: ")
17175 #?     8b/-> *(eax+0x14) 0/r32/eax
17176 #?     (write-int32-hex-buffered Stderr %eax)
17177 #?     (write-buffered Stderr Newline)
17178 #?     (flush Stderr)
17179 $lookup-or-create-constant:end:
17180     # . reclaim locals
17181     81 0/subop/add %esp 8/imm32
17182     # . restore registers
17183     5e/pop-to-esi
17184     58/pop-to-eax
17185     # . epilogue
17186     89/<- %esp 5/r32/ebp
17187     5d/pop-to-ebp
17188     c3/return
17189 
17190 # if addr var:
17191 #   container->var->type->right->left->value
17192 # otherwise
17193 #   container->var->type->value
17194 container-type:  # container: (addr stmt-var) -> result/eax: type-id
17195     # . prologue
17196     55/push-ebp
17197     89/<- %ebp 4/r32/esp
17198     #
17199     8b/-> *(ebp+8) 0/r32/eax
17200     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17201     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17202     {
17203       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
17204       74/jump-if-= break/disp8
17205       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17206       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17207     }
17208     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
17209 $container-type:end:
17210     # . epilogue
17211     89/<- %esp 5/r32/ebp
17212     5d/pop-to-ebp
17213     c3/return
17214 
17215 is-container?:  # t: type-id -> result/eax: boolean
17216     # . prologue
17217     55/push-ebp
17218     89/<- %ebp 4/r32/esp
17219     #
17220     8b/-> *(ebp+8) 0/r32/eax
17221     c1/shift 4/subop/left %eax 2/imm8
17222     3b/compare 0/r32/eax *Primitive-type-ids
17223     0f 9d/set-if->= %al
17224     81 4/subop/and %eax 0xff/imm32
17225 $is-container?:end:
17226     # . epilogue
17227     89/<- %esp 5/r32/ebp
17228     5d/pop-to-ebp
17229     c3/return
17230 
17231 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
17232     # . prologue
17233     55/push-ebp
17234     89/<- %ebp 4/r32/esp
17235     # . save registers
17236     50/push-eax
17237     51/push-ecx
17238     52/push-edx
17239     57/push-edi
17240     # edi = out
17241     8b/-> *(ebp+0xc) 7/r32/edi
17242     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
17243     68/push 0/imm32
17244     68/push 0/imm32
17245     89/<- %ecx 4/r32/esp
17246     # find-typeinfo(t, out)
17247     (find-typeinfo *(ebp+8) %edi)
17248     {
17249       # if (*out != 0) break
17250       81 7/subop/compare *edi 0/imm32
17251       0f 85/jump-if-!= break/disp32
17252 $find-or-create-typeinfo:create:
17253       # *out = allocate
17254       (allocate Heap *Typeinfo-size %edi)
17255       # var tmp/eax: (addr typeinfo) = lookup(*out)
17256       (lookup *edi *(edi+4))  # => eax
17257 #?     (write-buffered Stderr "created typeinfo at ")
17258 #?     (write-int32-hex-buffered Stderr %eax)
17259 #?     (write-buffered Stderr " for type-id ")
17260 #?     (write-int32-hex-buffered Stderr *(ebp+8))
17261 #?     (write-buffered Stderr Newline)
17262 #?     (flush Stderr)
17263       # tmp->id = t
17264       8b/-> *(ebp+8) 2/r32/edx
17265       89/<- *eax 2/r32/edx  # Typeinfo-id
17266       # tmp->fields = new table
17267       # . fields = new table
17268       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
17269       # . tmp->fields = fields
17270       8b/-> *ecx 2/r32/edx
17271       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
17272       8b/-> *(ecx+4) 2/r32/edx
17273       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
17274       # tmp->next = Program->types
17275       8b/-> *_Program-types 1/r32/ecx
17276       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
17277       8b/-> *_Program-types->payload 1/r32/ecx
17278       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
17279       # Program->types = out
17280       8b/-> *edi 1/r32/ecx
17281       89/<- *_Program-types 1/r32/ecx
17282       8b/-> *(edi+4) 1/r32/ecx
17283       89/<- *_Program-types->payload 1/r32/ecx
17284     }
17285 $find-or-create-typeinfo:end:
17286     # . reclaim locals
17287     81 0/subop/add %esp 8/imm32
17288     # . restore registers
17289     5f/pop-to-edi
17290     5a/pop-to-edx
17291     59/pop-to-ecx
17292     58/pop-to-eax
17293     # . epilogue
17294     89/<- %esp 5/r32/ebp
17295     5d/pop-to-ebp
17296     c3/return
17297 
17298 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
17299     # . prologue
17300     55/push-ebp
17301     89/<- %ebp 4/r32/esp
17302     # . save registers
17303     50/push-eax
17304     51/push-ecx
17305     52/push-edx
17306     57/push-edi
17307     # ecx = t
17308     8b/-> *(ebp+8) 1/r32/ecx
17309     # edi = out
17310     8b/-> *(ebp+0xc) 7/r32/edi
17311     # *out = Program->types
17312     8b/-> *_Program-types 0/r32/eax
17313     89/<- *edi 0/r32/eax
17314     8b/-> *_Program-types->payload 0/r32/eax
17315     89/<- *(edi+4) 0/r32/eax
17316     {
17317 $find-typeinfo:loop:
17318       # if (*out == 0) break
17319       81 7/subop/compare *edi 0/imm32
17320       74/jump-if-= break/disp8
17321 $find-typeinfo:check:
17322       # var tmp/eax: (addr typeinfo) = lookup(*out)
17323       (lookup *edi *(edi+4))  # => eax
17324       # if (tmp->id == t) break
17325       39/compare *eax 1/r32/ecx  # Typeinfo-id
17326       74/jump-if-= break/disp8
17327 $find-typeinfo:continue:
17328       # *out = tmp->next
17329       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
17330       89/<- *edi 2/r32/edx
17331       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
17332       89/<- *(edi+4) 2/r32/edx
17333       #
17334       eb/jump loop/disp8
17335     }
17336 $find-typeinfo:end:
17337     # . restore registers
17338     5f/pop-to-edi
17339     5a/pop-to-edx
17340     59/pop-to-ecx
17341     58/pop-to-eax
17342     # . epilogue
17343     89/<- %esp 5/r32/ebp
17344     5d/pop-to-ebp
17345     c3/return
17346 
17347 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
17348     # . prologue
17349     55/push-ebp
17350     89/<- %ebp 4/r32/esp
17351     # . save registers
17352     50/push-eax
17353     52/push-edx
17354     57/push-edi
17355     # var dest/edi: (handle typeinfo-entry)
17356     68/push 0/imm32
17357     68/push 0/imm32
17358     89/<- %edi 4/r32/esp
17359     # find-or-create-typeinfo-fields(T, f, dest)
17360     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
17361     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
17362     (lookup *edi *(edi+4))  # => eax
17363     89/<- %edi 0/r32/eax
17364     # if dest-addr->output-var doesn't exist, create it
17365     {
17366       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
17367       0f 85/jump-if-!= break/disp32
17368       # dest-addr->output-var = new var(dummy name, type, -1 offset)
17369       # . var name/eax: (handle array byte) = "field"
17370       68/push 0/imm32
17371       68/push 0/imm32
17372       89/<- %eax 4/r32/esp
17373       (slice-to-string Heap *(ebp+0xc) %eax)
17374       # . new var
17375       8d/copy-address *(edi+0xc) 2/r32/edx
17376       (new-var Heap  *eax *(eax+4)  %edx)
17377       # . reclaim name
17378       81 0/subop/add %esp 8/imm32
17379       # var result/edx: (addr var) = lookup(dest-addr->output-var)
17380       (lookup *(edi+0xc) *(edi+0x10))  # => eax
17381       89/<- %edx 0/r32/eax
17382       # result->type = new constant type
17383       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
17384       (allocate Heap *Type-tree-size %eax)
17385       (lookup *(edx+8) *(edx+0xc))  # => eax
17386       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
17387       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
17388       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
17389       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
17390       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
17391       # result->offset isn't filled out yet
17392       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
17393     }
17394     # out = dest-addr->output-var
17395     8b/-> *(ebp+0x10) 2/r32/edx
17396     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
17397     89/<- *edx 0/r32/eax
17398     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
17399     89/<- *(edx+4) 0/r32/eax
17400 $find-or-create-typeinfo-output-var:end:
17401     # . reclaim locals
17402     81 0/subop/add %esp 8/imm32
17403     # . restore registers
17404     5f/pop-to-edi
17405     5a/pop-to-edx
17406     58/pop-to-eax
17407     # . epilogue
17408     89/<- %esp 5/r32/ebp
17409     5d/pop-to-ebp
17410     c3/return
17411 
17412 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
17413     # . prologue
17414     55/push-ebp
17415     89/<- %ebp 4/r32/esp
17416     # . save registers
17417     50/push-eax
17418     56/push-esi
17419     57/push-edi
17420     # eax = lookup(T->fields)
17421     8b/-> *(ebp+8) 0/r32/eax
17422     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
17423     # edi = out
17424     8b/-> *(ebp+0x10) 7/r32/edi
17425     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
17426     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
17427     89/<- %esi 0/r32/eax
17428     # if src doesn't exist, allocate it
17429     {
17430       81 7/subop/compare *esi 0/imm32
17431       75/jump-if-!= break/disp8
17432       (allocate Heap *Typeinfo-entry-size %esi)
17433 #?       (write-buffered Stderr "handle at ")
17434 #?       (write-int32-hex-buffered Stderr %esi)
17435 #?       (write-buffered Stderr ": ")
17436 #?       (write-int32-hex-buffered Stderr *esi)
17437 #?       (write-buffered Stderr " ")
17438 #?       (write-int32-hex-buffered Stderr *(esi+4))
17439 #?       (write-buffered Stderr Newline)
17440 #?       (flush Stderr)
17441 #?       (lookup *esi *(esi+4))
17442 #?       (write-buffered Stderr "created typeinfo fields at ")
17443 #?       (write-int32-hex-buffered Stderr %esi)
17444 #?       (write-buffered Stderr " for ")
17445 #?       (write-int32-hex-buffered Stderr *(ebp+8))
17446 #?       (write-buffered Stderr Newline)
17447 #?       (flush Stderr)
17448     }
17449     # *out = src
17450     # . *edi = *src
17451     8b/-> *esi 0/r32/eax
17452     89/<- *edi 0/r32/eax
17453     8b/-> *(esi+4) 0/r32/eax
17454     89/<- *(edi+4) 0/r32/eax
17455 $find-or-create-typeinfo-fields:end:
17456     # . restore registers
17457     5f/pop-to-edi
17458     5e/pop-to-esi
17459     58/pop-to-eax
17460     # . epilogue
17461     89/<- %esp 5/r32/ebp
17462     5d/pop-to-ebp
17463     c3/return
17464 
17465 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
17466     # pseudocode:
17467     #   var line: (stream byte 512)
17468     #   curr-index = 0
17469     #   while true
17470     #     clear-stream(line)
17471     #     read-line-buffered(in, line)
17472     #     if line->write == 0
17473     #       abort
17474     #     word-slice = next-mu-token(line)
17475     #     if slice-empty?(word-slice)               # end of line
17476     #       continue
17477     #     if slice-equal?(word-slice, "}")
17478     #       break
17479     #     var v: (handle var) = parse-var-with-type(word-slice, line)
17480     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
17481     #     TODO: ensure that r->first is null
17482     #     r->index = curr-index
17483     #     curr-index++
17484     #     r->input-var = v
17485     #     if r->output-var == 0
17486     #       r->output-var = new literal
17487     #     TODO: ensure nothing else in line
17488     # t->total-size-in-bytes = -2 (not yet initialized)
17489     #
17490     # . prologue
17491     55/push-ebp
17492     89/<- %ebp 4/r32/esp
17493     # var curr-index: int at *(ebp-4)
17494     68/push 0/imm32
17495     # . save registers
17496     50/push-eax
17497     51/push-ecx
17498     52/push-edx
17499     53/push-ebx
17500     56/push-esi
17501     57/push-edi
17502     # edi = t
17503     8b/-> *(ebp+0xc) 7/r32/edi
17504     # var line/ecx: (stream byte 512)
17505     81 5/subop/subtract %esp 0x200/imm32
17506     68/push 0x200/imm32/size
17507     68/push 0/imm32/read
17508     68/push 0/imm32/write
17509     89/<- %ecx 4/r32/esp
17510     # var word-slice/edx: slice
17511     68/push 0/imm32/end
17512     68/push 0/imm32/start
17513     89/<- %edx 4/r32/esp
17514     # var v/esi: (handle var)
17515     68/push 0/imm32
17516     68/push 0/imm32
17517     89/<- %esi 4/r32/esp
17518     # var r/ebx: (handle typeinfo-entry)
17519     68/push 0/imm32
17520     68/push 0/imm32
17521     89/<- %ebx 4/r32/esp
17522     {
17523 $populate-mu-type:line-loop:
17524       (clear-stream %ecx)
17525       (read-line-buffered *(ebp+8) %ecx)
17526       # if (line->write == 0) abort
17527       81 7/subop/compare *ecx 0/imm32
17528       0f 84/jump-if-= $populate-mu-type:error1/disp32
17529 +--  6 lines: #?       # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
17535       (next-mu-token %ecx %edx)
17536       # if slice-empty?(word-slice) continue
17537       (slice-empty? %edx)  # => eax
17538       3d/compare-eax-and 0/imm32
17539       0f 85/jump-if-!= loop/disp32
17540       # if slice-equal?(word-slice, "}") break
17541       (slice-equal? %edx "}")
17542       3d/compare-eax-and 0/imm32
17543       0f 85/jump-if-!= break/disp32
17544 $populate-mu-type:parse-element:
17545       # v = parse-var-with-type(word-slice, first-line)
17546       # must do this first to strip the trailing ':' from word-slice before
17547       # using it in find-or-create-typeinfo-fields below
17548       # TODO: clean up that mutation in parse-var-with-type
17549       (parse-var-with-type %edx %ecx %esi *(ebp+0x10) *(ebp+0x14))
17550       # if v is an addr, abort
17551       (lookup *esi *(esi+4))  # => eax
17552       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17553       (is-mu-addr-type? %eax)  # => eax
17554       3d/compare-eax-and 0/imm32/false
17555       0f 85/jump-if-!= $populate-mu-type:error2/disp32
17556       # if v is an array, abort  (we could support it, but initialization gets complex)
17557       (lookup *esi *(esi+4))  # => eax
17558       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17559       (is-mu-array-type? %eax)  # => eax
17560       3d/compare-eax-and 0/imm32/false
17561       0f 85/jump-if-!= $populate-mu-type:error3/disp32
17562       # if v is a byte, abort
17563       (lookup *esi *(esi+4))  # => eax
17564       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17565       (is-simple-mu-type? %eax 8)  # byte => eax
17566       3d/compare-eax-and 0/imm32/false
17567       0f 85/jump-if-!= $populate-mu-type:error4/disp32
17568       # if v is a slice, abort
17569       (lookup *esi *(esi+4))  # => eax
17570       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17571       (is-simple-mu-type? %eax 0xc)  # slice => eax
17572       3d/compare-eax-and 0/imm32/false
17573       0f 85/jump-if-!= $populate-mu-type:error5/disp32
17574       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
17575       (lookup *esi *(esi+4))  # => eax
17576       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17577       (is-mu-stream-type? %eax)  # => eax
17578       3d/compare-eax-and 0/imm32/false
17579       0f 85/jump-if-!= $populate-mu-type:error6/disp32
17580       # var tmp/ecx
17581       51/push-ecx
17582 $populate-mu-type:create-typeinfo-fields:
17583       # var r/ebx: (handle typeinfo-entry)
17584       (find-or-create-typeinfo-fields %edi %edx %ebx)
17585       # r->index = curr-index
17586       (lookup *ebx *(ebx+4))  # => eax
17587       8b/-> *(ebp-4) 1/r32/ecx
17588 #?       (write-buffered Stderr "saving index ")
17589 #?       (write-int32-hex-buffered Stderr %ecx)
17590 #?       (write-buffered Stderr " at ")
17591 #?       (write-int32-hex-buffered Stderr %edi)
17592 #?       (write-buffered Stderr Newline)
17593 #?       (flush Stderr)
17594       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
17595       # ++curr-index
17596       ff 0/subop/increment *(ebp-4)
17597 $populate-mu-type:set-input-type:
17598       # r->input-var = v
17599       8b/-> *esi 1/r32/ecx
17600       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
17601       8b/-> *(esi+4) 1/r32/ecx
17602       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
17603       # restore line
17604       59/pop-to-ecx
17605       {
17606 $populate-mu-type:create-output-type:
17607         # if (r->output-var == 0) create a new var with some placeholder data
17608         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
17609         75/jump-if-!= break/disp8
17610         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
17611         (new-literal Heap %edx %eax)
17612       }
17613       e9/jump loop/disp32
17614     }
17615 $populate-mu-type:invalidate-total-size-in-bytes:
17616     # Offsets and total size may not be accurate here since we may not yet
17617     # have encountered the element types.
17618     # We'll recompute them separately after parsing the entire program.
17619     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
17620 $populate-mu-type:end:
17621     # . reclaim locals
17622     81 0/subop/add %esp 0x224/imm32
17623     # . restore registers
17624     5f/pop-to-edi
17625     5e/pop-to-esi
17626     5b/pop-to-ebx
17627     5a/pop-to-edx
17628     59/pop-to-ecx
17629     58/pop-to-eax
17630     # reclaim curr-index
17631     81 0/subop/add %esp 4/imm32
17632     # . epilogue
17633     89/<- %esp 5/r32/ebp
17634     5d/pop-to-ebp
17635     c3/return
17636 
17637 $populate-mu-type:error1:
17638     # error("incomplete type definition '" t->name "'\n")
17639     (write-buffered *(ebp+0x10) "incomplete type definition '")
17640     (type-name *edi)  # Typeinfo-id => eax
17641     (write-buffered *(ebp+0x10) %eax)
17642     (write-buffered *(ebp+0x10) "\n")
17643     (flush *(ebp+0x10))
17644     (stop *(ebp+0x14) 1)
17645     # never gets here
17646 
17647 $populate-mu-type:error2:
17648     (write-buffered *(ebp+0x10) "type ")
17649     (type-name *edi)  # Typeinfo-id => eax
17650     (write-buffered *(ebp+0x10) %eax)
17651     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
17652     (flush *(ebp+0x10))
17653     (stop *(ebp+0x14) 1)
17654     # never gets here
17655 
17656 $populate-mu-type:error3:
17657     (write-buffered *(ebp+0x10) "type ")
17658     (type-name *edi)  # Typeinfo-id => eax
17659     (write-buffered *(ebp+0x10) %eax)
17660     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
17661     (flush *(ebp+0x10))
17662     (stop *(ebp+0x14) 1)
17663     # never gets here
17664 
17665 $populate-mu-type:error4:
17666     (write-buffered *(ebp+0x10) "type ")
17667     (type-name *edi)  # Typeinfo-id => eax
17668     (write-buffered *(ebp+0x10) %eax)
17669     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
17670     (flush *(ebp+0x10))
17671     (stop *(ebp+0x14) 1)
17672     # never gets here
17673 
17674 $populate-mu-type:error5:
17675     (write-buffered *(ebp+0x10) "type ")
17676     (type-name *edi)  # Typeinfo-id => eax
17677     (write-buffered *(ebp+0x10) %eax)
17678     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
17679     (flush *(ebp+0x10))
17680     (stop *(ebp+0x14) 1)
17681     # never gets here
17682 
17683 $populate-mu-type:error6:
17684     (write-buffered *(ebp+0x10) "type ")
17685     (type-name *edi)  # Typeinfo-id => eax
17686     (write-buffered *(ebp+0x10) %eax)
17687     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
17688     (flush *(ebp+0x10))
17689     (stop *(ebp+0x14) 1)
17690     # never gets here
17691 
17692 type-name:  # index: int -> result/eax: (addr array byte)
17693     # . prologue
17694     55/push-ebp
17695     89/<- %ebp 4/r32/esp
17696     #
17697     (index Type-id *(ebp+8))
17698 $type-name:end:
17699     # . epilogue
17700     89/<- %esp 5/r32/ebp
17701     5d/pop-to-ebp
17702     c3/return
17703 
17704 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
17705     # . prologue
17706     55/push-ebp
17707     89/<- %ebp 4/r32/esp
17708     # . save registers
17709     56/push-esi
17710     # TODO: bounds-check index
17711     # esi = arr
17712     8b/-> *(ebp+8) 6/r32/esi
17713     # eax = index
17714     8b/-> *(ebp+0xc) 0/r32/eax
17715     # eax = *(arr + 12 + index)
17716     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
17717 $index:end:
17718     # . restore registers
17719     5e/pop-to-esi
17720     # . epilogue
17721     89/<- %esp 5/r32/ebp
17722     5d/pop-to-ebp
17723     c3/return
17724 
17725 #######################################################
17726 # Compute type sizes
17727 #######################################################
17728 
17729 # Compute the sizes of all user-defined types.
17730 # We'll need the sizes of their elements, which may be other user-defined
17731 # types, which we will compute as needed.
17732 
17733 # Initially, all user-defined types have their sizes set to -2 (invalid)
17734 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
17735     # . prologue
17736     55/push-ebp
17737     89/<- %ebp 4/r32/esp
17738 $populate-mu-type-sizes:total-sizes:
17739     # var curr/eax: (addr typeinfo) = lookup(Program->types)
17740     (lookup *_Program-types *_Program-types->payload)  # => eax
17741     {
17742       # if (curr == null) break
17743       3d/compare-eax-and 0/imm32/null
17744       74/jump-if-= break/disp8
17745       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
17746       # curr = lookup(curr->next)
17747       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
17748       eb/jump loop/disp8
17749     }
17750 $populate-mu-type-sizes:offsets:
17751     # curr = *Program->types
17752     (lookup *_Program-types *_Program-types->payload)  # => eax
17753     {
17754       # if (curr == null) break
17755       3d/compare-eax-and 0/imm32/null
17756       74/jump-if-= break/disp8
17757       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
17758       # curr = curr->next
17759       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
17760       eb/jump loop/disp8
17761     }
17762 $populate-mu-type-sizes:end:
17763     # . epilogue
17764     89/<- %esp 5/r32/ebp
17765     5d/pop-to-ebp
17766     c3/return
17767 
17768 # compute sizes of all fields, recursing as necessary
17769 # sum up all their sizes to arrive at total size
17770 # fields may be out of order, but that doesn't affect the answer
17771 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
17772     # . prologue
17773     55/push-ebp
17774     89/<- %ebp 4/r32/esp
17775     # . save registers
17776     50/push-eax
17777     51/push-ecx
17778     52/push-edx
17779     56/push-esi
17780     57/push-edi
17781     # esi = T
17782     8b/-> *(ebp+8) 6/r32/esi
17783     # if T is already computed, return
17784     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
17785     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
17786     # if T is being computed, abort
17787     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
17788     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
17789     # tag T (-2 to -1) to avoid infinite recursion
17790     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
17791     # var total-size/edi: int = 0
17792     bf/copy-to-edi 0/imm32
17793     # - for every field, if it's a user-defined type, compute its size
17794     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
17795     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
17796     89/<- %ecx 0/r32/eax
17797     # var table-size/edx: int = table->write
17798     8b/-> *ecx 2/r32/edx  # stream-write
17799     # var curr/ecx: (addr table_row) = table->data
17800     8d/copy-address *(ecx+0xc) 1/r32/ecx
17801     # var max/edx: (addr table_row) = table->data + table->write
17802     8d/copy-address *(ecx+edx) 2/r32/edx
17803     {
17804 $populate-mu-type-sizes-in-type:loop:
17805       # if (curr >= max) break
17806       39/compare %ecx 2/r32/edx
17807       73/jump-if-addr>= break/disp8
17808       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
17809       (lookup *(ecx+8) *(ecx+0xc))  # => eax
17810       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
17811       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
17812       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
17813       # compute size of t->input-var
17814       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
17815       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
17816       # result += eax
17817       01/add-to %edi 0/r32/eax
17818       # curr += row-size
17819       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
17820       #
17821       eb/jump loop/disp8
17822     }
17823     # - save result
17824     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
17825 $populate-mu-type-sizes-in-type:end:
17826     # . restore registers
17827     5f/pop-to-edi
17828     5e/pop-to-esi
17829     5a/pop-to-edx
17830     59/pop-to-ecx
17831     58/pop-to-eax
17832     # . epilogue
17833     89/<- %esp 5/r32/ebp
17834     5d/pop-to-ebp
17835     c3/return
17836 
17837 $populate-mu-type-sizes-in-type:abort:
17838     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
17839     (flush *(ebp+0xc))
17840     (stop *(ebp+0x10) 1)
17841     # never gets here
17842 
17843 # Analogous to size-of, except we need to compute what size-of can just read
17844 # off the right data structures.
17845 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17846     # . prologue
17847     55/push-ebp
17848     89/<- %ebp 4/r32/esp
17849     # . push registers
17850     51/push-ecx
17851     # var t/ecx: (addr type-tree) = lookup(v->type)
17852     8b/-> *(ebp+8) 1/r32/ecx
17853     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17854     89/<- %ecx 0/r32/eax
17855     # if (t->is-atom == false) t = lookup(t->left)
17856     {
17857       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
17858       75/jump-if-!= break/disp8
17859       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
17860       89/<- %ecx 0/r32/eax
17861     }
17862     # TODO: ensure t is an atom
17863     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
17864 $compute-size-of-var:end:
17865     # . restore registers
17866     59/pop-to-ecx
17867     # . epilogue
17868     89/<- %esp 5/r32/ebp
17869     5d/pop-to-ebp
17870     c3/return
17871 
17872 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17873     # . prologue
17874     55/push-ebp
17875     89/<- %ebp 4/r32/esp
17876     # . save registers
17877     51/push-ecx
17878     # var out/ecx: (handle typeinfo)
17879     68/push 0/imm32
17880     68/push 0/imm32
17881     89/<- %ecx 4/r32/esp
17882     # eax = t
17883     8b/-> *(ebp+8) 0/r32/eax
17884     # if t is a literal, return 0
17885     3d/compare-eax-and 0/imm32/literal
17886     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
17887     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
17888     3d/compare-eax-and 8/imm32/byte
17889     {
17890       75/jump-if-!= break/disp8
17891       b8/copy-to-eax 4/imm32
17892       eb/jump $compute-size-of-type-id:end/disp8
17893     }
17894     # if t is a handle, return 8
17895     3d/compare-eax-and 4/imm32/handle
17896     {
17897       75/jump-if-!= break/disp8
17898       b8/copy-to-eax 8/imm32
17899       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
17900     }
17901     # if t is a slice, return 8
17902     3d/compare-eax-and 0xc/imm32/slice
17903     {
17904       75/jump-if-!= break/disp8
17905       b8/copy-to-eax 8/imm32
17906       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
17907     }
17908     # if t is a user-defined type, compute its size
17909     # TODO: support non-atom type
17910     (find-typeinfo %eax %ecx)
17911     {
17912       81 7/subop/compare *ecx 0/imm32
17913       74/jump-if-= break/disp8
17914 $compute-size-of-type-id:user-defined:
17915       (lookup *ecx *(ecx+4))  # => eax
17916       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
17917       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
17918       eb/jump $compute-size-of-type-id:end/disp8
17919     }
17920     # otherwise return the word size
17921     b8/copy-to-eax 4/imm32
17922 $compute-size-of-type-id:end:
17923     # . reclaim locals
17924     81 0/subop/add %esp 8/imm32
17925     # . restore registers
17926     59/pop-to-ecx
17927     # . epilogue
17928     89/<- %esp 5/r32/ebp
17929     5d/pop-to-ebp
17930     c3/return
17931 
17932 # at this point we have total sizes for all user-defined types
17933 # compute offsets for each element
17934 # complication: fields may be out of order
17935 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
17936     # . prologue
17937     55/push-ebp
17938     89/<- %ebp 4/r32/esp
17939     # . save registers
17940     50/push-eax
17941     51/push-ecx
17942     52/push-edx
17943     53/push-ebx
17944     56/push-esi
17945     57/push-edi
17946 #?     (dump-typeinfos "aaa\n")
17947     # var curr-offset/edi: int = 0
17948     bf/copy-to-edi 0/imm32
17949     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
17950     8b/-> *(ebp+8) 1/r32/ecx
17951     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
17952     89/<- %ecx 0/r32/eax
17953     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
17954     8b/-> *ecx 2/r32/edx  # stream-write
17955     c1 5/subop/shift-right-logical  %edx 4/imm8
17956     # var i/ebx: int = 0
17957     bb/copy-to-ebx 0/imm32
17958     {
17959 $populate-mu-type-offsets:loop:
17960       39/compare %ebx 2/r32/edx
17961       0f 8d/jump-if->= break/disp32
17962 #?       (write-buffered Stderr "looking up index ")
17963 #?       (write-int32-hex-buffered Stderr %ebx)
17964 #?       (write-buffered Stderr " in ")
17965 #?       (write-int32-hex-buffered Stderr *(ebp+8))
17966 #?       (write-buffered Stderr Newline)
17967 #?       (flush Stderr)
17968       # var v/esi: (addr typeinfo-entry)
17969       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
17970       89/<- %esi 0/r32/eax
17971       # if v is null, silently move on; we'll emit a nice error message while type-checking
17972       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
17973       74/jump-if-= $populate-mu-type-offsets:end/disp8
17974       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
17975       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
17976       74/jump-if-= $populate-mu-type-offsets:end/disp8
17977       # v->output-var->offset = curr-offset
17978       # . eax: (addr var)
17979       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
17980       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
17981       # curr-offset += size-of(v->input-var)
17982       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
17983       (size-of %eax)  # => eax
17984       01/add-to %edi 0/r32/eax
17985       # ++i
17986       43/increment-ebx
17987       e9/jump loop/disp32
17988     }
17989 $populate-mu-type-offsets:end:
17990     # . restore registers
17991     5f/pop-to-edi
17992     5e/pop-to-esi
17993     5b/pop-to-ebx
17994     5a/pop-to-edx
17995     59/pop-to-ecx
17996     58/pop-to-eax
17997     # . epilogue
17998     89/<- %esp 5/r32/ebp
17999     5d/pop-to-ebp
18000     c3/return
18001 
18002 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)
18003     # . prologue
18004     55/push-ebp
18005     89/<- %ebp 4/r32/esp
18006     # . save registers
18007     51/push-ecx
18008     52/push-edx
18009     53/push-ebx
18010     56/push-esi
18011     57/push-edi
18012     # esi = table
18013     8b/-> *(ebp+8) 6/r32/esi
18014     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
18015     8d/copy-address *(esi+0xc) 1/r32/ecx
18016     # var max/edx: (addr byte) = &table->data[table->write]
18017     8b/-> *esi 2/r32/edx
18018     8d/copy-address *(ecx+edx) 2/r32/edx
18019     {
18020 $locate-typeinfo-entry-with-index:loop:
18021       39/compare %ecx 2/r32/edx
18022       73/jump-if-addr>= break/disp8
18023       # var v/eax: (addr typeinfo-entry)
18024       (lookup *(ecx+8) *(ecx+0xc))  # => eax
18025       # if (v->index == idx) return v
18026       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
18027 #?       (write-buffered Stderr "comparing ")
18028 #?       (write-int32-hex-buffered Stderr %ebx)
18029 #?       (write-buffered Stderr " and ")
18030 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
18031 #?       (write-buffered Stderr Newline)
18032 #?       (flush Stderr)
18033       39/compare *(ebp+0xc) 3/r32/ebx
18034       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
18035       # curr += Typeinfo-entry-size
18036       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
18037       #
18038       eb/jump loop/disp8
18039     }
18040     # return 0
18041     b8/copy-to-eax 0/imm32
18042 $locate-typeinfo-entry-with-index:end:
18043 #?     (write-buffered Stderr "returning ")
18044 #?     (write-int32-hex-buffered Stderr %eax)
18045 #?     (write-buffered Stderr Newline)
18046 #?     (flush Stderr)
18047     # . restore registers
18048     5f/pop-to-edi
18049     5e/pop-to-esi
18050     5b/pop-to-ebx
18051     5a/pop-to-edx
18052     59/pop-to-ecx
18053     # . epilogue
18054     89/<- %esp 5/r32/ebp
18055     5d/pop-to-ebp
18056     c3/return
18057 
18058 dump-typeinfos:  # hdr: (addr array byte)
18059     # . prologue
18060     55/push-ebp
18061     89/<- %ebp 4/r32/esp
18062     # . save registers
18063     50/push-eax
18064     #
18065     (write-buffered Stderr *(ebp+8))
18066     (flush Stderr)
18067     # var curr/eax: (addr typeinfo) = lookup(Program->types)
18068     (lookup *_Program-types *_Program-types->payload)  # => eax
18069     {
18070       # if (curr == null) break
18071       3d/compare-eax-and 0/imm32
18072       74/jump-if-= break/disp8
18073       (write-buffered Stderr "---\n")
18074       (flush Stderr)
18075       (dump-typeinfo %eax)
18076       # curr = lookup(curr->next)
18077       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
18078       eb/jump loop/disp8
18079     }
18080 $dump-typeinfos:end:
18081     # . restore registers
18082     58/pop-to-eax
18083     # . epilogue
18084     89/<- %esp 5/r32/ebp
18085     5d/pop-to-ebp
18086     c3/return
18087 
18088 dump-typeinfo:  # in: (addr typeinfo)
18089     # . prologue
18090     55/push-ebp
18091     89/<- %ebp 4/r32/esp
18092     # . save registers
18093     50/push-eax
18094     51/push-ecx
18095     52/push-edx
18096     53/push-ebx
18097     56/push-esi
18098     57/push-edi
18099     # esi = in
18100     8b/-> *(ebp+8) 6/r32/esi
18101     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
18102     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
18103     89/<- %ecx 0/r32/eax
18104     (write-buffered Stderr "id:")
18105     (write-int32-hex-buffered Stderr *esi)
18106     (write-buffered Stderr "\n")
18107     (write-buffered Stderr "fields @ ")
18108     (write-int32-hex-buffered Stderr %ecx)
18109     (write-buffered Stderr Newline)
18110     (flush Stderr)
18111     (write-buffered Stderr "  write: ")
18112     (write-int32-hex-buffered Stderr *ecx)
18113     (write-buffered Stderr Newline)
18114     (flush Stderr)
18115     (write-buffered Stderr "  read: ")
18116     (write-int32-hex-buffered Stderr *(ecx+4))
18117     (write-buffered Stderr Newline)
18118     (flush Stderr)
18119     (write-buffered Stderr "  size: ")
18120     (write-int32-hex-buffered Stderr *(ecx+8))
18121     (write-buffered Stderr Newline)
18122     (flush Stderr)
18123     # var table-size/edx: int = table->write
18124     8b/-> *ecx 2/r32/edx  # stream-write
18125     # var curr/ecx: (addr table_row) = table->data
18126     8d/copy-address *(ecx+0xc) 1/r32/ecx
18127     # var max/edx: (addr table_row) = table->data + table->write
18128     8d/copy-address *(ecx+edx) 2/r32/edx
18129     {
18130 $dump-typeinfo:loop:
18131       # if (curr >= max) break
18132       39/compare %ecx 2/r32/edx
18133       0f 83/jump-if-addr>= break/disp32
18134       (write-buffered Stderr "  row:\n")
18135       (write-buffered Stderr "    key: ")
18136       (write-int32-hex-buffered Stderr *ecx)
18137       (write-buffered Stderr ",")
18138       (write-int32-hex-buffered Stderr *(ecx+4))
18139       (write-buffered Stderr " = '")
18140       (lookup *ecx *(ecx+4))
18141       (write-buffered Stderr %eax)
18142       (write-buffered Stderr "' @ ")
18143       (write-int32-hex-buffered Stderr %eax)
18144       (write-buffered Stderr Newline)
18145       (flush Stderr)
18146       (write-buffered Stderr "    value: ")
18147       (write-int32-hex-buffered Stderr *(ecx+8))
18148       (write-buffered Stderr ",")
18149       (write-int32-hex-buffered Stderr *(ecx+0xc))
18150       (write-buffered Stderr " = typeinfo-entry@")
18151       (lookup *(ecx+8) *(ecx+0xc))
18152       (write-int32-hex-buffered Stderr %eax)
18153       (write-buffered Stderr Newline)
18154       (flush Stderr)
18155       (write-buffered Stderr "        input var@")
18156       (dump-var 5 %eax)
18157       (lookup *(ecx+8) *(ecx+0xc))
18158       (write-buffered Stderr "        index: ")
18159       (write-int32-hex-buffered Stderr *(eax+8))
18160       (write-buffered Stderr Newline)
18161       (flush Stderr)
18162       (write-buffered Stderr "        output var@")
18163       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
18164       (dump-var 5 %eax)
18165       (flush Stderr)
18166       # curr += row-size
18167       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
18168       #
18169       e9/jump loop/disp32
18170     }
18171 $dump-typeinfo:end:
18172     # . restore registers
18173     5f/pop-to-edi
18174     5e/pop-to-esi
18175     5b/pop-to-ebx
18176     5a/pop-to-edx
18177     59/pop-to-ecx
18178     58/pop-to-eax
18179     # . epilogue
18180     89/<- %esp 5/r32/ebp
18181     5d/pop-to-ebp
18182     c3/return
18183 
18184 dump-var:  # indent: int, v: (addr handle var)
18185     # . prologue
18186     55/push-ebp
18187     89/<- %ebp 4/r32/esp
18188     # . save registers
18189     50/push-eax
18190     53/push-ebx
18191     # eax = v
18192     8b/-> *(ebp+0xc) 0/r32/eax
18193     #
18194     (write-int32-hex-buffered Stderr *eax)
18195     (write-buffered Stderr ",")
18196     (write-int32-hex-buffered Stderr *(eax+4))
18197     (write-buffered Stderr "->")
18198     (lookup *eax *(eax+4))
18199     (write-int32-hex-buffered Stderr %eax)
18200     (write-buffered Stderr Newline)
18201     (flush Stderr)
18202     {
18203       3d/compare-eax-and 0/imm32
18204       0f 84/jump-if-= break/disp32
18205       (emit-indent Stderr *(ebp+8))
18206       (write-buffered Stderr "name: ")
18207       89/<- %ebx 0/r32/eax
18208       (write-int32-hex-buffered Stderr *ebx)  # Var-name
18209       (write-buffered Stderr ",")
18210       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
18211       (write-buffered Stderr "->")
18212       (lookup *ebx *(ebx+4))  # Var-name
18213       (write-int32-hex-buffered Stderr %eax)
18214       {
18215         3d/compare-eax-and 0/imm32
18216         74/jump-if-= break/disp8
18217         (write-buffered Stderr Space)
18218         (write-buffered Stderr %eax)
18219       }
18220       (write-buffered Stderr Newline)
18221       (flush Stderr)
18222       (emit-indent Stderr *(ebp+8))
18223       (write-buffered Stderr "block depth: ")
18224       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
18225       (write-buffered Stderr Newline)
18226       (flush Stderr)
18227       (emit-indent Stderr *(ebp+8))
18228       (write-buffered Stderr "stack offset: ")
18229       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
18230       (write-buffered Stderr Newline)
18231       (flush Stderr)
18232       (emit-indent Stderr *(ebp+8))
18233       (write-buffered Stderr "reg: ")
18234       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
18235       (write-buffered Stderr ",")
18236       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
18237       (write-buffered Stderr "->")
18238       (flush Stderr)
18239       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
18240       (write-int32-hex-buffered Stderr %eax)
18241       {
18242         3d/compare-eax-and 0/imm32
18243         74/jump-if-= break/disp8
18244         (write-buffered Stderr Space)
18245         (write-buffered Stderr %eax)
18246       }
18247       (write-buffered Stderr Newline)
18248       (flush Stderr)
18249     }
18250 $dump-var:end:
18251     # . restore registers
18252     5b/pop-to-ebx
18253     58/pop-to-eax
18254     # . epilogue
18255     89/<- %esp 5/r32/ebp
18256     5d/pop-to-ebp
18257     c3/return
18258 
18259 #######################################################
18260 # Type-checking
18261 #######################################################
18262 
18263 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
18264     # . prologue
18265     55/push-ebp
18266     89/<- %ebp 4/r32/esp
18267     # . save registers
18268     50/push-eax
18269     # var curr/eax: (addr function) = lookup(Program->functions)
18270     (lookup *_Program-functions *_Program-functions->payload)  # => eax
18271     {
18272 $check-mu-types:loop:
18273       # if (curr == null) break
18274       3d/compare-eax-and 0/imm32
18275       0f 84/jump-if-= break/disp32
18276 +--  8 lines: #?       # dump curr->name -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18284       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
18285       # curr = lookup(curr->next)
18286       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
18287       e9/jump loop/disp32
18288     }
18289 $check-mu-types:end:
18290     # . restore registers
18291     58/pop-to-eax
18292     # . epilogue
18293     89/<- %esp 5/r32/ebp
18294     5d/pop-to-ebp
18295     c3/return
18296 
18297 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18298     # . prologue
18299     55/push-ebp
18300     89/<- %ebp 4/r32/esp
18301     # . save registers
18302     50/push-eax
18303     56/push-esi
18304     # esi = f
18305     8b/-> *(ebp+8) 6/r32/esi
18306     # outputs
18307     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
18308     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
18309     # body
18310     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
18311     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
18312     # if function has no outputs, we're done
18313     81 7/subop/compare *(esi+0x10) 0/imm32
18314     74/jump-if-= $check-mu-function:end/disp8
18315     # some final checks on body
18316     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
18317     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
18318 $check-mu-function:end:
18319     # . restore registers
18320     5e/pop-to-esi
18321     58/pop-to-eax
18322     # . epilogue
18323     89/<- %esp 5/r32/ebp
18324     5d/pop-to-ebp
18325     c3/return
18326 
18327 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18328     # . prologue
18329     55/push-ebp
18330     89/<- %ebp 4/r32/esp
18331     # . save registers
18332     50/push-eax
18333     # eax = block
18334     8b/-> *(ebp+8) 0/r32/eax
18335     # var stmts/eax: (addr list stmt) = lookup(block->statements)
18336     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
18337     #
18338     {
18339 $check-mu-block:check-empty:
18340       3d/compare-eax-and 0/imm32
18341       0f 84/jump-if-= break/disp32
18342       # emit block->statements
18343       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18344     }
18345 $check-mu-block:end:
18346     # . restore registers
18347     58/pop-to-eax
18348     # . epilogue
18349     89/<- %esp 5/r32/ebp
18350     5d/pop-to-ebp
18351     c3/return
18352 
18353 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18354     # . prologue
18355     55/push-ebp
18356     89/<- %ebp 4/r32/esp
18357     # . save registers
18358     50/push-eax
18359     56/push-esi
18360     # esi = stmts
18361     8b/-> *(ebp+8) 6/r32/esi
18362     {
18363 $check-mu-stmt-list:loop:
18364       81 7/subop/compare %esi 0/imm32
18365       0f 84/jump-if-= break/disp32
18366       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
18367       (lookup *esi *(esi+4))  # List-value List-value => eax
18368       {
18369 $check-mu-stmt-list:check-for-block:
18370         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
18371         75/jump-if-!= break/disp8
18372 $check-mu-stmt-list:block:
18373         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18374         eb/jump $check-mu-stmt-list:continue/disp8
18375       }
18376       {
18377 $check-mu-stmt-list:check-for-stmt1:
18378         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
18379         0f 85/jump-if-!= break/disp32
18380 $check-mu-stmt-list:stmt1:
18381         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18382         eb/jump $check-mu-stmt-list:continue/disp8
18383       }
18384       {
18385 $check-mu-stmt-list:check-for-reg-var-def:
18386         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
18387         0f 85/jump-if-!= break/disp32
18388 $check-mu-stmt-list:reg-var-def:
18389         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18390         eb/jump $check-mu-stmt-list:continue/disp8
18391       }
18392 $check-mu-stmt-list:continue:
18393       # TODO: raise an error on unrecognized Stmt-tag
18394       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
18395       89/<- %esi 0/r32/eax
18396       e9/jump loop/disp32
18397     }
18398 $check-mu-stmt-list:end:
18399     # . restore registers
18400     5e/pop-to-esi
18401     58/pop-to-eax
18402     # . epilogue
18403     89/<- %esp 5/r32/ebp
18404     5d/pop-to-ebp
18405     c3/return
18406 
18407 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18408     # . prologue
18409     55/push-ebp
18410     89/<- %ebp 4/r32/esp
18411     # . save registers
18412     50/push-eax
18413     # - if stmt's operation matches a primitive, check against it
18414     (has-primitive-name? *(ebp+8))  # => eax
18415     3d/compare-eax-and 0/imm32/false
18416     {
18417       74/jump-if-= break/disp8
18418       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18419       e9/jump $check-mu-stmt:end/disp32
18420     }
18421     # - otherwise find a function to check against
18422     # var f/eax: (addr function) = lookup(*Program->functions)
18423     (lookup *_Program-functions *_Program-functions->payload)  # => eax
18424     (find-matching-function %eax *(ebp+8))  # => eax
18425     3d/compare-eax-and 0/imm32
18426     {
18427       74/jump-if-= break/disp8
18428       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18429       eb/jump $check-mu-stmt:end/disp8
18430     }
18431     # var f/eax: (addr function) = lookup(*Program->signatures)
18432     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
18433     (find-matching-function %eax *(ebp+8))  # => eax
18434     3d/compare-eax-and 0/imm32
18435     {
18436       74/jump-if-= break/disp8
18437       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18438       eb/jump $check-mu-stmt:end/disp8
18439     }
18440     # - otherwise abort
18441     e9/jump $check-mu-stmt:unknown-call/disp32
18442 $check-mu-stmt:end:
18443     # . restore registers
18444     58/pop-to-eax
18445     # . epilogue
18446     89/<- %esp 5/r32/ebp
18447     5d/pop-to-ebp
18448     c3/return
18449 
18450 $check-mu-stmt:unknown-call:
18451     (write-buffered *(ebp+0x10) "unknown function '")
18452     8b/-> *(ebp+8) 0/r32/eax
18453     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
18454     (write-buffered *(ebp+0x10) %eax)
18455     (write-buffered *(ebp+0x10) "'\n")
18456     (flush *(ebp+0x10))
18457     (stop *(ebp+0x14) 1)
18458     # never gets here
18459 
18460 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
18461     # . prologue
18462     55/push-ebp
18463     89/<- %ebp 4/r32/esp
18464     # . save registers
18465     51/push-ecx
18466     56/push-esi
18467     # var name/esi: (addr array byte) = lookup(stmt->operation)
18468     8b/-> *(ebp+8) 6/r32/esi
18469     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
18470     89/<- %esi 0/r32/eax
18471     # if (name == "return") return true
18472     (string-equal? %esi "return")  # => eax
18473     3d/compare-eax-and 0/imm32/false
18474     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18475     # if (name == "get") return true
18476     (string-equal? %esi "get")  # => eax
18477     3d/compare-eax-and 0/imm32/false
18478     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18479     # if (name == "index") return true
18480     (string-equal? %esi "index")  # => eax
18481     3d/compare-eax-and 0/imm32/false
18482     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18483     # if (name == "length") return true
18484     (string-equal? %esi "length")  # => eax
18485     3d/compare-eax-and 0/imm32/false
18486     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18487     # if (name == "compute-offset") return true
18488     (string-equal? %esi "compute-offset")  # => eax
18489     3d/compare-eax-and 0/imm32/false
18490     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18491     # if (name == "copy-object") return true
18492     (string-equal? %esi "copy-object")  # => eax
18493     3d/compare-eax-and 0/imm32/false
18494     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18495     # if (name == "allocate") return true
18496     (string-equal? %esi "allocate")  # => eax
18497     3d/compare-eax-and 0/imm32/false
18498     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18499     # if (name == "populate") return true
18500     (string-equal? %esi "populate")  # => eax
18501     3d/compare-eax-and 0/imm32/false
18502     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18503     # if (name == "populate-stream") return true
18504     (string-equal? %esi "populate-stream")  # => eax
18505     3d/compare-eax-and 0/imm32/false
18506     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18507     # if (name == "read-from-stream") return true
18508     (string-equal? %esi "read-from-stream")  # => eax
18509     3d/compare-eax-and 0/imm32/false
18510     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18511     # if (name == "write-to-stream") return true
18512     (string-equal? %esi "write-to-stream")  # => eax
18513     3d/compare-eax-and 0/imm32/false
18514     0f 85/jump-if-!= $has-primitive-name?:end/disp32
18515     # var curr/ecx: (addr primitive) = Primitives
18516     b9/copy-to-ecx Primitives/imm32
18517     {
18518 $has-primitive-name?:loop:
18519       # if (curr == null) break
18520       81 7/subop/compare %ecx 0/imm32
18521       74/jump-if-= break/disp8
18522       # if (primitive->name == name) return true
18523       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
18524 #?       (write-buffered Stderr %eax)
18525 #?       (write-buffered Stderr Newline)
18526 #?       (flush Stderr)
18527       (string-equal? %esi %eax)  # => eax
18528       3d/compare-eax-and 0/imm32/false
18529       75/jump-if-!= $has-primitive-name?:end/disp8
18530 $has-primitive-name?:next-primitive:
18531       # curr = curr->next
18532       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
18533       89/<- %ecx 0/r32/eax
18534       #
18535       e9/jump loop/disp32
18536     }
18537     # return null
18538     b8/copy-to-eax 0/imm32
18539 $has-primitive-name?:end:
18540     # . restore registers
18541     5e/pop-to-esi
18542     59/pop-to-ecx
18543     # . epilogue
18544     89/<- %esp 5/r32/ebp
18545     5d/pop-to-ebp
18546     c3/return
18547 
18548 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18549     # . prologue
18550     55/push-ebp
18551     89/<- %ebp 4/r32/esp
18552     # . save registers
18553     50/push-eax
18554     51/push-ecx
18555     # var op/ecx: (addr array byte) = lookup(stmt->operation)
18556     8b/-> *(ebp+8) 0/r32/eax
18557     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
18558     89/<- %ecx 0/r32/eax
18559     # if (op == "copy") check-mu-copy-stmt
18560     {
18561       (string-equal? %ecx "copy")  # => eax
18562       3d/compare-eax-and 0/imm32/false
18563       74/jump-if-= break/disp8
18564       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18565       e9/jump $check-mu-primitive:end/disp32
18566     }
18567     # if (op == "copy-to") check-mu-copy-to-stmt
18568     {
18569       (string-equal? %ecx "copy-to")  # => eax
18570       3d/compare-eax-and 0/imm32/false
18571       74/jump-if-= break/disp8
18572       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18573       e9/jump $check-mu-primitive:end/disp32
18574     }
18575     # if (op == "compare") check-mu-compare-stmt
18576     {
18577       (string-equal? %ecx "compare")  # => eax
18578       3d/compare-eax-and 0/imm32/false
18579       74/jump-if-= break/disp8
18580       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18581       e9/jump $check-mu-primitive:end/disp32
18582     }
18583     # if (op == "address") check-mu-address-stmt
18584     {
18585       (string-equal? %ecx "address")  # => eax
18586       3d/compare-eax-and 0/imm32/false
18587       74/jump-if-= break/disp8
18588       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18589       e9/jump $check-mu-primitive:end/disp32
18590     }
18591     # if (op == "return") check-mu-return-stmt
18592     {
18593       (string-equal? %ecx "return")  # => eax
18594       3d/compare-eax-and 0/imm32/false
18595       74/jump-if-= break/disp8
18596       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18597       e9/jump $check-mu-primitive:end/disp32
18598     }
18599     # if (op == "get") check-mu-get-stmt
18600     {
18601       (string-equal? %ecx "get")  # => eax
18602       3d/compare-eax-and 0/imm32/false
18603       74/jump-if-= break/disp8
18604       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18605       e9/jump $check-mu-primitive:end/disp32
18606     }
18607     # if (op == "index") check-mu-index-stmt
18608     {
18609       (string-equal? %ecx "index")  # => eax
18610       3d/compare-eax-and 0/imm32/false
18611       74/jump-if-= break/disp8
18612       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18613       e9/jump $check-mu-primitive:end/disp32
18614     }
18615     # if (op == "length") check-mu-length-stmt
18616     {
18617       (string-equal? %ecx "length")  # => eax
18618       3d/compare-eax-and 0/imm32/false
18619       74/jump-if-= break/disp8
18620       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18621       e9/jump $check-mu-primitive:end/disp32
18622     }
18623     # if (op == "compute-offset") check-mu-compute-offset-stmt
18624     {
18625       (string-equal? %ecx "compute-offset")  # => eax
18626       3d/compare-eax-and 0/imm32/false
18627       74/jump-if-= break/disp8
18628       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18629       e9/jump $check-mu-primitive:end/disp32
18630     }
18631     # if (op == "copy-object") check-mu-copy-object-stmt
18632     {
18633       (string-equal? %ecx "copy-object")  # => eax
18634       3d/compare-eax-and 0/imm32/false
18635       74/jump-if-= break/disp8
18636       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18637       e9/jump $check-mu-primitive:end/disp32
18638     }
18639     # if (op == "allocate") check-mu-allocate-stmt
18640     {
18641       (string-equal? %ecx "allocate")  # => eax
18642       3d/compare-eax-and 0/imm32/false
18643       74/jump-if-= break/disp8
18644       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18645       e9/jump $check-mu-primitive:end/disp32
18646     }
18647     # if (op == "populate") check-mu-populate-stmt
18648     {
18649       (string-equal? %ecx "populate")  # => eax
18650       3d/compare-eax-and 0/imm32/false
18651       74/jump-if-= break/disp8
18652       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18653       e9/jump $check-mu-primitive:end/disp32
18654     }
18655     # if (op == "populate-stream") check-mu-populate-stream-stmt
18656     {
18657       (string-equal? %ecx "populate-stream")  # => eax
18658       3d/compare-eax-and 0/imm32/false
18659       74/jump-if-= break/disp8
18660       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18661       e9/jump $check-mu-primitive:end/disp32
18662     }
18663     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
18664     {
18665       (string-equal? %ecx "read-from-stream")  # => eax
18666       3d/compare-eax-and 0/imm32/false
18667       74/jump-if-= break/disp8
18668       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18669       e9/jump $check-mu-primitive:end/disp32
18670     }
18671     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
18672     {
18673       (string-equal? %ecx "write-to-stream")  # => eax
18674       3d/compare-eax-and 0/imm32/false
18675       74/jump-if-= break/disp8
18676       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18677       e9/jump $check-mu-primitive:end/disp32
18678     }
18679     # if (op == "convert") check-mu-convert-stmt
18680     {
18681       (string-equal? %ecx "convert")  # => eax
18682       3d/compare-eax-and 0/imm32/false
18683       74/jump-if-= break/disp8
18684       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18685       e9/jump $check-mu-primitive:end/disp32
18686     }
18687     # otherwise check-numberlike-stmt
18688     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18689 $check-mu-primitive:end:
18690     # . restore registers
18691     59/pop-to-ecx
18692     58/pop-to-eax
18693     # . epilogue
18694     89/<- %esp 5/r32/ebp
18695     5d/pop-to-ebp
18696     c3/return
18697 
18698 # by default, Mu primitives should only operate on 'number-like' types
18699 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18700     # . prologue
18701     55/push-ebp
18702     89/<- %ebp 4/r32/esp
18703     # . save registers
18704     50/push-eax
18705     51/push-ecx
18706     56/push-esi
18707     # esi = stmt
18708     8b/-> *(ebp+8) 6/r32/esi
18709     # var gas/ecx: int = 2
18710     b9/copy-to-ecx 2/imm32
18711     # - check at most 1 output
18712     # var output/eax: (addr stmt-var) = stmt->outputs
18713     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
18714     {
18715       3d/compare-eax-and 0/imm32
18716       74/jump-if-= break/disp8
18717 $check-mu-numberlike-primitive:output:
18718       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18719       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18720       3d/compare-eax-and 0/imm32
18721       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
18722       # check output is in a register
18723       # --gas
18724       49/decrement-ecx
18725     }
18726     # - check first inout
18727     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18728     {
18729       3d/compare-eax-and 0/imm32
18730       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
18731 $check-mu-numberlike-primitive:first-inout:
18732       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18733       # --gas
18734       49/decrement-ecx
18735     }
18736     # - check second inout
18737     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18738     {
18739       3d/compare-eax-and 0/imm32
18740       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
18741 $check-mu-numberlike-primitive:second-inout:
18742       # is a second inout allowed?
18743       81 7/subop/compare %ecx 0/imm32
18744       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
18745 $check-mu-numberlike-primitive:second-inout-permitted:
18746       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18747     }
18748 $check-mu-numberlike-primitive:third-inout:
18749     # if there's a third arg, raise an error
18750     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
18751     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
18752 $check-mu-numberlike-primitive:end:
18753     # . restore registers
18754     5e/pop-to-esi
18755     59/pop-to-ecx
18756     58/pop-to-eax
18757     # . epilogue
18758     89/<- %esp 5/r32/ebp
18759     5d/pop-to-ebp
18760     c3/return
18761 
18762 $check-mu-numberlike-primitive:error-too-many-inouts:
18763     (write-buffered *(ebp+0x10) "fn ")
18764     8b/-> *(ebp+0xc) 0/r32/eax
18765     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18766     (write-buffered *(ebp+0x10) %eax)
18767     (write-buffered *(ebp+0x10) ": stmt ")
18768     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
18769     (write-buffered *(ebp+0x10) %eax)
18770     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
18771     (flush *(ebp+0x10))
18772     (stop *(ebp+0x14) 1)
18773     # never gets here
18774 
18775 $check-mu-numberlike-primitive:error-too-many-outputs:
18776     (write-buffered *(ebp+0x10) "fn ")
18777     8b/-> *(ebp+0xc) 0/r32/eax
18778     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18779     (write-buffered *(ebp+0x10) %eax)
18780     (write-buffered *(ebp+0x10) ": stmt ")
18781     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
18782     (write-buffered *(ebp+0x10) %eax)
18783     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
18784     (flush *(ebp+0x10))
18785     (stop *(ebp+0x14) 1)
18786     # never gets here
18787 
18788 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18789     # . prologue
18790     55/push-ebp
18791     89/<- %ebp 4/r32/esp
18792     # . save registers
18793     50/push-eax
18794     56/push-esi
18795     # var t/esi: (addr type-tree) = lookup(v->value->type)
18796     8b/-> *(ebp+8) 0/r32/eax
18797     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18798     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18799     89/<- %esi 0/r32/eax
18800 $check-mu-numberlike-arg:check-literal:
18801     # if t is an int, return
18802     (is-simple-mu-type? %esi 0)  # literal => eax
18803     3d/compare-eax-and 0/imm32/false
18804     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
18805 $check-mu-numberlike-arg:check-addr:
18806     # if t is an addr and v is dereferenced, return whether t->payload is an addr
18807     {
18808       (is-mu-addr-type? %esi)  # => eax
18809       3d/compare-eax-and 0/imm32/false
18810       74/jump-if-= break/disp8
18811       8b/-> *(ebp+8) 0/r32/eax
18812       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
18813       3d/compare-eax-and 0/imm32/false
18814       {
18815         74/jump-if-= break/disp8
18816         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
18817         # if t->right is null, t = t->left
18818         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
18819         {
18820           75/jump-if-!= break/disp8
18821           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18822         }
18823         (is-mu-addr-type? %eax)  # => eax
18824         3d/compare-eax-and 0/imm32/false
18825         74/jump-if-= $check-mu-numberlike-arg:end/disp8
18826       }
18827     }
18828 $check-mu-numberlike-arg:output-checks:
18829     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
18830 $check-mu-numberlike-arg:end:
18831     # . restore registers
18832     5e/pop-to-esi
18833     58/pop-to-eax
18834     # . epilogue
18835     89/<- %esp 5/r32/ebp
18836     5d/pop-to-ebp
18837     c3/return
18838 
18839 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18840     # . prologue
18841     55/push-ebp
18842     89/<- %ebp 4/r32/esp
18843     # . save registers
18844     50/push-eax
18845     56/push-esi
18846     # var t/esi: (addr type-tree) = lookup(v->value->type)
18847     8b/-> *(ebp+8) 0/r32/eax
18848     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18849     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18850     89/<- %esi 0/r32/eax
18851 $check-mu-numberlike-output:check-int:
18852     # if t is an int, return
18853     (is-simple-mu-type? %esi 1)  # int => eax
18854     3d/compare-eax-and 0/imm32/false
18855     0f 85/jump-if-!= $check-mu-numberlike-output:end/disp32
18856 $check-mu-numberlike-output:check-float:
18857     # if t is a float, return
18858     (is-simple-mu-type? %esi 0xf)  # float => eax
18859     3d/compare-eax-and 0/imm32/false
18860     75/jump-if-!= $check-mu-numberlike-output:end/disp8
18861 $check-mu-numberlike-output:check-boolean:
18862     # if t is a boolean, return
18863     (is-simple-mu-type? %esi 5)  # boolean => eax
18864     3d/compare-eax-and 0/imm32/false
18865     75/jump-if-!= $check-mu-numberlike-output:end/disp8
18866 $check-mu-numberlike-output:check-byte:
18867     # if t is a byte, return
18868     (is-simple-mu-type? %esi 8)  # byte => eax
18869     3d/compare-eax-and 0/imm32/false
18870     75/jump-if-!= $check-mu-numberlike-output:end/disp8
18871 $check-mu-numberlike-output:check-code-point:
18872     # if t is a code-point, return
18873     (is-simple-mu-type? %esi 0xd)  # code-point => eax
18874     3d/compare-eax-and 0/imm32/false
18875     75/jump-if-!= $check-mu-numberlike-output:end/disp8
18876 $check-mu-numberlike-output:check-grapheme:
18877     # if t is a grapheme, return
18878     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
18879     3d/compare-eax-and 0/imm32/false
18880     75/jump-if-!= $check-mu-numberlike-output:end/disp8
18881     e9/jump $check-mu-numberlike-output:fail/disp32
18882 $check-mu-numberlike-output:end:
18883     # . restore registers
18884     5e/pop-to-esi
18885     58/pop-to-eax
18886     # . epilogue
18887     89/<- %esp 5/r32/ebp
18888     5d/pop-to-ebp
18889     c3/return
18890 
18891 $check-mu-numberlike-output:fail:
18892     # otherwise raise an error
18893     (write-buffered *(ebp+0x14) "fn ")
18894     8b/-> *(ebp+0x10) 0/r32/eax
18895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18896     (write-buffered *(ebp+0x14) %eax)
18897     (write-buffered *(ebp+0x14) ": stmt ")
18898     8b/-> *(ebp+0xc) 0/r32/eax
18899     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
18900     (write-buffered *(ebp+0x14) %eax)
18901     (write-buffered *(ebp+0x14) ": '")
18902     8b/-> *(ebp+8) 0/r32/eax
18903     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18904     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18905     (write-buffered *(ebp+0x14) %eax)
18906     (write-buffered *(ebp+0x14) "' must be a non-addr scalar\n")
18907     (flush *(ebp+0x14))
18908     (stop *(ebp+0x18) 1)
18909     # never gets here
18910 
18911 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18912     # . prologue
18913     55/push-ebp
18914     89/<- %ebp 4/r32/esp
18915     # . save registers
18916     50/push-eax
18917     51/push-ecx
18918     52/push-edx
18919     56/push-esi
18920     57/push-edi
18921     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
18922     81 5/subop/subtract %esp 0x60/imm32
18923     68/push 0x60/imm32/size
18924     68/push 0/imm32/read
18925     68/push 0/imm32/write
18926     89/<- %edx 4/r32/esp
18927 $check-mu-copy-stmt:get-output:
18928     # esi = stmt
18929     8b/-> *(ebp+8) 6/r32/esi
18930     # var output/edi: (addr stmt-var) = stmt->outputs
18931     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
18932     89/<- %edi 0/r32/eax
18933     # zero outputs
18934     3d/compare-eax-and 0/imm32
18935     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
18936     # > 1 output
18937     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
18938     3d/compare-eax-and 0/imm32
18939     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
18940 $check-mu-copy-stmt:get-inout:
18941     # var inout/esi: (addr stmt-var) = stmt->inouts
18942     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18943     89/<- %esi 0/r32/eax
18944     # zero inouts
18945     3d/compare-eax-and 0/imm32
18946     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
18947     # > 1 inout
18948     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
18949     3d/compare-eax-and 0/imm32
18950     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
18951 $check-mu-copy-stmt:types:
18952     # var inout-type/ecx: (addr type-tree) = inout->value->type
18953     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
18954     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18955     89/<- %ecx 0/r32/eax
18956     # if (inout->is-deref?) inout-type = inout-type->payload
18957     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
18958     3d/compare-eax-and 0/imm32/false
18959     {
18960       74/jump-if-= break/disp8
18961       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18962       # if inout-type->right is null, t = inout-type->left
18963       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
18964       {
18965         75/jump-if-!= break/disp8
18966         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18967       }
18968       89/<- %ecx 0/r32/eax
18969     }
18970     # if output not in register, abort
18971     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
18972     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
18973     3d/compare-eax-and 0/imm32
18974     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
18975     # if inout is not a scalar, abort
18976     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
18977     (size-of %eax)  # => eax
18978     3d/compare-eax-and 4/imm32
18979     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
18980     # var output-type/eax: (addr type-tree) = output->value->type
18981     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
18982     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18983     # if (inout-type == output-type) return
18984     (type-match? %eax %ecx %edx)  # => eax
18985     3d/compare-eax-and 0/imm32
18986     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
18987     # if output is an addr and inout is 0, return
18988     {
18989       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
18990       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18991       (is-mu-addr-type? %eax)  # => eax
18992       3d/compare-eax-and 0/imm32/false
18993       74/jump-if-= break/disp8
18994       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
18995       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18996       (string-equal? %eax "0")  # => eax
18997       3d/compare-eax-and 0/imm32/false
18998       74/jump-if-= break/disp8
18999       eb/jump $check-mu-copy-stmt:end/disp8
19000     }
19001     # if output is not number-like, abort
19002     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19003 $check-mu-copy-stmt:end:
19004     # . reclaim locals
19005     81 0/subop/add %esp 0x6c/imm32
19006     # . restore registers
19007     5f/pop-to-edi
19008     5e/pop-to-esi
19009     5a/pop-to-edx
19010     59/pop-to-ecx
19011     58/pop-to-eax
19012     # . epilogue
19013     89/<- %esp 5/r32/ebp
19014     5d/pop-to-ebp
19015     c3/return
19016 
19017 $check-mu-copy-stmt:error-no-inout:
19018     (write-buffered *(ebp+0x10) "fn ")
19019     8b/-> *(ebp+0xc) 0/r32/eax
19020     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19021     (write-buffered *(ebp+0x10) %eax)
19022     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
19023     (flush *(ebp+0x10))
19024     (stop *(ebp+0x14) 1)
19025     # never gets here
19026 
19027 $check-mu-copy-stmt:error-too-many-inouts:
19028     (write-buffered *(ebp+0x10) "fn ")
19029     8b/-> *(ebp+0xc) 0/r32/eax
19030     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19031     (write-buffered *(ebp+0x10) %eax)
19032     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
19033     (flush *(ebp+0x10))
19034     (stop *(ebp+0x14) 1)
19035     # never gets here
19036 
19037 $check-mu-copy-stmt:error-no-output:
19038     (write-buffered *(ebp+0x10) "fn ")
19039     8b/-> *(ebp+0xc) 0/r32/eax
19040     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19041     (write-buffered *(ebp+0x10) %eax)
19042     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
19043     (flush *(ebp+0x10))
19044     (stop *(ebp+0x14) 1)
19045     # never gets here
19046 
19047 $check-mu-copy-stmt:error-output-not-in-register:
19048     (write-buffered *(ebp+0x10) "fn ")
19049     8b/-> *(ebp+0xc) 0/r32/eax
19050     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19051     (write-buffered *(ebp+0x10) %eax)
19052     (write-buffered *(ebp+0x10) ": stmt copy: output '")
19053     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19054     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19055     (write-buffered *(ebp+0x10) %eax)
19056     (write-buffered *(ebp+0x10) "' not in a register\n")
19057     (flush *(ebp+0x10))
19058     (stop *(ebp+0x14) 1)
19059     # never gets here
19060 
19061 $check-mu-copy-stmt:error-too-many-outputs:
19062     (write-buffered *(ebp+0x10) "fn ")
19063     8b/-> *(ebp+0xc) 0/r32/eax
19064     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19065     (write-buffered *(ebp+0x10) %eax)
19066     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
19067     (flush *(ebp+0x10))
19068     (stop *(ebp+0x14) 1)
19069     # never gets here
19070 
19071 $check-mu-copy-stmt:error-inout-too-large:
19072     (write-buffered *(ebp+0x10) "fn ")
19073     8b/-> *(ebp+0xc) 0/r32/eax
19074     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19075     (write-buffered *(ebp+0x10) %eax)
19076     (write-buffered *(ebp+0x10) ": stmt copy: '")
19077     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19078     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19079     (write-buffered *(ebp+0x10) %eax)
19080     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
19081     (flush *(ebp+0x10))
19082     (stop *(ebp+0x14) 1)
19083     # never gets here
19084 
19085 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19086     # . prologue
19087     55/push-ebp
19088     89/<- %ebp 4/r32/esp
19089     # . save registers
19090     50/push-eax
19091     51/push-ecx
19092     52/push-edx
19093     53/push-ebx
19094     56/push-esi
19095     57/push-edi
19096     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
19097     81 5/subop/subtract %esp 0x60/imm32
19098     68/push 0x60/imm32/size
19099     68/push 0/imm32/read
19100     68/push 0/imm32/write
19101     89/<- %edx 4/r32/esp
19102     # esi = stmt
19103     8b/-> *(ebp+8) 6/r32/esi
19104 $check-mu-copy-to-stmt:check-for-output:
19105     # if stmt->outputs abort
19106     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19107     3d/compare-eax-and 0/imm32
19108     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
19109 $check-mu-copy-to-stmt:get-dest:
19110     # var dest/edi: (addr stmt-var) = stmt->inouts
19111     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19112     89/<- %edi 0/r32/eax
19113     # zero inouts
19114     3d/compare-eax-and 0/imm32
19115     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
19116 $check-mu-copy-to-stmt:get-src:
19117     # var src/esi: (addr stmt-var) = dest->next
19118     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19119     89/<- %esi 0/r32/eax
19120     # 1 inout
19121     3d/compare-eax-and 0/imm32
19122     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
19123     # > 2 inouts
19124     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19125     3d/compare-eax-and 0/imm32
19126     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
19127 $check-mu-copy-to-stmt:types:
19128     # var src-type/ecx: (addr type-tree) = src->value->type
19129     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19130     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19131     89/<- %ecx 0/r32/eax
19132     # if src not in register or literal, abort
19133     # (we can't use stack-offset because it hasn't been computed yet)
19134     {
19135       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19136       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
19137       (is-simple-mu-type? %eax 0)  # => eax
19138       3d/compare-eax-and 0/imm32
19139       75/jump-if-!= break/disp8
19140       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19141       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19142       3d/compare-eax-and 0/imm32
19143       75/jump-if-!= break/disp8
19144       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
19145     }
19146     # if src is not a scalar, abort
19147     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19148     (size-of %eax)  # => eax
19149     3d/compare-eax-and 4/imm32
19150     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
19151     # var dest-type/ebx: (addr type-tree) = dest->value->type
19152     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19153     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19154     89/<- %ebx 0/r32/eax
19155     # if (dest->is-deref?) dest-type = dest-type->payload
19156     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
19157     3d/compare-eax-and 0/imm32/false
19158     {
19159       74/jump-if-= break/disp8
19160       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
19161       # if dest-type->right is null, dest-type = dest-type->left
19162       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19163       {
19164         75/jump-if-!= break/disp8
19165         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19166       }
19167       89/<- %ebx 0/r32/eax
19168     }
19169     # if (src-type == dest-type) return
19170     (type-match? %ebx %ecx %edx)  # => eax
19171     3d/compare-eax-and 0/imm32
19172     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
19173     # if dest is an addr and src is 0, return
19174     {
19175       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19176       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19177       (is-mu-addr-type? %eax)  # => eax
19178       3d/compare-eax-and 0/imm32/false
19179       74/jump-if-= break/disp8
19180       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19181       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19182       (string-equal? %eax "0")  # => eax
19183       3d/compare-eax-and 0/imm32/false
19184       74/jump-if-= break/disp8
19185       eb/jump $check-mu-copy-to-stmt:end/disp8
19186     }
19187     # if dest is not number-like, abort
19188     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19189 $check-mu-copy-to-stmt:end:
19190     # . reclaim locals
19191     81 0/subop/add %esp 0x6c/imm32
19192     # . restore registers
19193     5f/pop-to-edi
19194     5e/pop-to-esi
19195     5b/pop-to-ebx
19196     5a/pop-to-edx
19197     59/pop-to-ecx
19198     58/pop-to-eax
19199     # . epilogue
19200     89/<- %esp 5/r32/ebp
19201     5d/pop-to-ebp
19202     c3/return
19203 
19204 $check-mu-copy-to-stmt:error-incorrect-inouts:
19205     (write-buffered *(ebp+0x10) "fn ")
19206     8b/-> *(ebp+0xc) 0/r32/eax
19207     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19208     (write-buffered *(ebp+0x10) %eax)
19209     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
19210     (flush *(ebp+0x10))
19211     (stop *(ebp+0x14) 1)
19212     # never gets here
19213 
19214 $check-mu-copy-to-stmt:error-too-many-outputs:
19215     (write-buffered *(ebp+0x10) "fn ")
19216     8b/-> *(ebp+0xc) 0/r32/eax
19217     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19218     (write-buffered *(ebp+0x10) %eax)
19219     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
19220     (flush *(ebp+0x10))
19221     (stop *(ebp+0x14) 1)
19222     # never gets here
19223 
19224 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
19225     (write-buffered *(ebp+0x10) "fn ")
19226     8b/-> *(ebp+0xc) 0/r32/eax
19227     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19228     (write-buffered *(ebp+0x10) %eax)
19229     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
19230     (flush *(ebp+0x10))
19231     (stop *(ebp+0x14) 1)
19232     # never gets here
19233 
19234 $check-mu-copy-to-stmt:error-src-too-large:
19235     (write-buffered *(ebp+0x10) "fn ")
19236     8b/-> *(ebp+0xc) 0/r32/eax
19237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19238     (write-buffered *(ebp+0x10) %eax)
19239     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
19240     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19241     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19242     (write-buffered *(ebp+0x10) %eax)
19243     (write-buffered *(ebp+0x10) "' is too large to copy\n")
19244     (flush *(ebp+0x10))
19245     (stop *(ebp+0x14) 1)
19246     # never gets here
19247 
19248 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19249     # . prologue
19250     55/push-ebp
19251     89/<- %ebp 4/r32/esp
19252     # . save registers
19253     50/push-eax
19254     51/push-ecx
19255     52/push-edx
19256     53/push-ebx
19257     56/push-esi
19258     57/push-edi
19259     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
19260     81 5/subop/subtract %esp 0x60/imm32
19261     68/push 0x60/imm32/size
19262     68/push 0/imm32/read
19263     68/push 0/imm32/write
19264     89/<- %edx 4/r32/esp
19265     # esi = stmt
19266     8b/-> *(ebp+8) 6/r32/esi
19267 $check-mu-compare-stmt:check-for-output:
19268     # if stmt->outputs abort
19269     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19270     3d/compare-eax-and 0/imm32
19271     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
19272 $check-mu-compare-stmt:get-left:
19273     # var left/edi: (addr stmt-var) = stmt->inouts
19274     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19275     89/<- %edi 0/r32/eax
19276     # zero inouts
19277     3d/compare-eax-and 0/imm32
19278     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
19279 $check-mu-compare-stmt:get-right:
19280     # var right/esi: (addr stmt-var) = left->next
19281     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19282     89/<- %esi 0/r32/eax
19283     # 1 inout
19284     3d/compare-eax-and 0/imm32
19285     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
19286     # > 2 inouts
19287     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19288     3d/compare-eax-and 0/imm32
19289     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
19290     # if both inouts are in memory, abort
19291     {
19292 $check-mu-compare-stmt:both-in-mem:
19293       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19294       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
19295       (is-simple-mu-type? %eax 0)  # => eax
19296       3d/compare-eax-and 0/imm32
19297       0f 85/jump-if-!= break/disp32
19298       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19299       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19300       3d/compare-eax-and 0/imm32
19301       75/jump-if-!= break/disp8
19302       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19303       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
19304       (is-simple-mu-type? %eax 0)  # => eax
19305       3d/compare-eax-and 0/imm32
19306       75/jump-if-!= break/disp8
19307       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19308       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19309       3d/compare-eax-and 0/imm32
19310       75/jump-if-!= break/disp8
19311       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
19312     }
19313 $check-mu-compare-stmt:types:
19314     # var right-type/ecx: (addr type-tree) = right->value->type
19315     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19316     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19317     89/<- %ecx 0/r32/eax
19318     # if (right->is-deref?) right-type = right-type->payload
19319     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
19320     3d/compare-eax-and 0/imm32/false
19321     {
19322       74/jump-if-= break/disp8
19323       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19324       # if right-type->right is null, right-type = right-type->left
19325       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19326       {
19327         75/jump-if-!= break/disp8
19328         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19329       }
19330       89/<- %ecx 0/r32/eax
19331     }
19332     # if right is not a scalar, abort
19333     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19334     (size-of %eax)  # => eax
19335     3d/compare-eax-and 4/imm32
19336     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
19337     # if left is not a scalar, abort
19338     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19339     (size-of %eax)  # => eax
19340     3d/compare-eax-and 4/imm32
19341     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
19342     # var left-type/ebx: (addr type-tree) = left->value->type
19343     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19344     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19345     89/<- %ebx 0/r32/eax
19346     # if (left->is-deref?) left-type = left-type->payload
19347     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
19348     3d/compare-eax-and 0/imm32/false
19349     {
19350       74/jump-if-= break/disp8
19351       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
19352       # if left-type->right is null, left-type = left-type->left
19353       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19354       {
19355         75/jump-if-!= break/disp8
19356         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19357       }
19358       89/<- %ebx 0/r32/eax
19359     }
19360     # if (left-type == right-type) return
19361     (type-match? %ebx %ecx %edx)  # => eax
19362     3d/compare-eax-and 0/imm32
19363     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
19364     # if left is an addr and right is 0, return
19365     {
19366       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19367       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19368       (is-mu-addr-type? %eax)  # => eax
19369       3d/compare-eax-and 0/imm32/false
19370       74/jump-if-= break/disp8
19371       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19372       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19373       (string-equal? %eax "0")  # => eax
19374       3d/compare-eax-and 0/imm32/false
19375       74/jump-if-= break/disp8
19376       eb/jump $check-mu-compare-stmt:end/disp8
19377     }
19378     # if left is not number-like, abort
19379     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19380 $check-mu-compare-stmt:end:
19381     # . reclaim locals
19382     81 0/subop/add %esp 0x6c/imm32
19383     # . restore registers
19384     5f/pop-to-edi
19385     5e/pop-to-esi
19386     5b/pop-to-ebx
19387     5a/pop-to-edx
19388     59/pop-to-ecx
19389     58/pop-to-eax
19390     # . epilogue
19391     89/<- %esp 5/r32/ebp
19392     5d/pop-to-ebp
19393     c3/return
19394 
19395 $check-mu-compare-stmt:error-incorrect-inouts:
19396     (write-buffered *(ebp+0x10) "fn ")
19397     8b/-> *(ebp+0xc) 0/r32/eax
19398     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19399     (write-buffered *(ebp+0x10) %eax)
19400     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
19401     (flush *(ebp+0x10))
19402     (stop *(ebp+0x14) 1)
19403     # never gets here
19404 
19405 $check-mu-compare-stmt:error-too-many-outputs:
19406     (write-buffered *(ebp+0x10) "fn ")
19407     8b/-> *(ebp+0xc) 0/r32/eax
19408     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19409     (write-buffered *(ebp+0x10) %eax)
19410     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
19411     (flush *(ebp+0x10))
19412     (stop *(ebp+0x14) 1)
19413     # never gets here
19414 
19415 $check-mu-compare-stmt:error-both-in-memory:
19416     (write-buffered *(ebp+0x10) "fn ")
19417     8b/-> *(ebp+0xc) 0/r32/eax
19418     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19419     (write-buffered *(ebp+0x10) %eax)
19420     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
19421     (flush *(ebp+0x10))
19422     (stop *(ebp+0x14) 1)
19423     # never gets here
19424 
19425 $check-mu-compare-stmt:error-left-too-large:
19426     (write-buffered *(ebp+0x10) "fn ")
19427     8b/-> *(ebp+0xc) 0/r32/eax
19428     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19429     (write-buffered *(ebp+0x10) %eax)
19430     (write-buffered *(ebp+0x10) ": stmt compare: '")
19431     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19432     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19433     (write-buffered *(ebp+0x10) %eax)
19434     (write-buffered *(ebp+0x10) "' is too large to compare\n")
19435     (flush *(ebp+0x10))
19436     (stop *(ebp+0x14) 1)
19437     # never gets here
19438 
19439 $check-mu-compare-stmt:error-right-too-large:
19440     (write-buffered *(ebp+0x10) "fn ")
19441     8b/-> *(ebp+0xc) 0/r32/eax
19442     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19443     (write-buffered *(ebp+0x10) %eax)
19444     (write-buffered *(ebp+0x10) ": stmt compare: '")
19445     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19446     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19447     (write-buffered *(ebp+0x10) %eax)
19448     (write-buffered *(ebp+0x10) "' is too large to compare\n")
19449     (flush *(ebp+0x10))
19450     (stop *(ebp+0x14) 1)
19451     # never gets here
19452 
19453 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19454     # . prologue
19455     55/push-ebp
19456     89/<- %ebp 4/r32/esp
19457     # . save registers
19458     50/push-eax
19459     51/push-ecx
19460     52/push-edx
19461     56/push-esi
19462     57/push-edi
19463 $check-mu-address-stmt:get-output:
19464     # esi = stmt
19465     8b/-> *(ebp+8) 6/r32/esi
19466     # var output/edi: (addr stmt-var) = stmt->outputs
19467     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19468     89/<- %edi 0/r32/eax
19469     # zero outputs
19470     3d/compare-eax-and 0/imm32
19471     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
19472     # > 1 output
19473     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19474     3d/compare-eax-and 0/imm32
19475     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
19476 $check-mu-address-stmt:get-inout:
19477     # var inout/esi: (addr stmt-var) = stmt->inouts
19478     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19479     89/<- %esi 0/r32/eax
19480     # zero inouts
19481     3d/compare-eax-and 0/imm32
19482     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
19483     # > 1 inout
19484     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19485     3d/compare-eax-and 0/imm32
19486     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
19487 $check-mu-address-stmt:types:
19488     # if output not in register, abort
19489     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19490     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19491     3d/compare-eax-and 0/imm32
19492     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
19493     # var output-type/edx: (addr type-tree) = output->value->type
19494     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19495     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19496     89/<- %edx 0/r32/eax
19497     # if output-type not an addr, abort
19498     (is-mu-addr-type? %edx)  # => eax
19499     3d/compare-eax-and 0/imm32/false
19500     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
19501     # output-type = output-type->right
19502     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
19503     # if output-type->right is null, output-type = output-type->left
19504     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19505     {
19506       75/jump-if-!= break/disp8
19507       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19508     }
19509     89/<- %edx 0/r32/eax
19510     # var inout-type/ecx: (addr type-tree) = inout->value->type
19511     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19512     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19513     89/<- %ecx 0/r32/eax
19514     # if (inout->is-deref?) inout-type = inout-type->payload
19515     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
19516     3d/compare-eax-and 0/imm32/false
19517     {
19518       74/jump-if-= break/disp8
19519       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19520       # if inout-type->right is null, t = inout-type->left
19521       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19522       {
19523         75/jump-if-!= break/disp8
19524         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19525       }
19526       89/<- %ecx 0/r32/eax
19527     }
19528     # if (inout-type != output-type) abort
19529     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
19530     3d/compare-eax-and 0/imm32
19531     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
19532 $check-mu-address-stmt:end:
19533     # . restore registers
19534     5f/pop-to-edi
19535     5e/pop-to-esi
19536     5a/pop-to-edx
19537     59/pop-to-ecx
19538     58/pop-to-eax
19539     # . epilogue
19540     89/<- %esp 5/r32/ebp
19541     5d/pop-to-ebp
19542     c3/return
19543 
19544 $check-mu-address-stmt:error-no-inout:
19545     (write-buffered *(ebp+0x10) "fn ")
19546     8b/-> *(ebp+0xc) 0/r32/eax
19547     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19548     (write-buffered *(ebp+0x10) %eax)
19549     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
19550     (flush *(ebp+0x10))
19551     (stop *(ebp+0x14) 1)
19552     # never gets here
19553 
19554 $check-mu-address-stmt:error-too-many-inouts:
19555     (write-buffered *(ebp+0x10) "fn ")
19556     8b/-> *(ebp+0xc) 0/r32/eax
19557     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19558     (write-buffered *(ebp+0x10) %eax)
19559     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
19560     (flush *(ebp+0x10))
19561     (stop *(ebp+0x14) 1)
19562     # never gets here
19563 
19564 $check-mu-address-stmt:error-no-output:
19565     (write-buffered *(ebp+0x10) "fn ")
19566     8b/-> *(ebp+0xc) 0/r32/eax
19567     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19568     (write-buffered *(ebp+0x10) %eax)
19569     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
19570     (flush *(ebp+0x10))
19571     (stop *(ebp+0x14) 1)
19572     # never gets here
19573 
19574 $check-mu-address-stmt:error-output-not-in-register:
19575     (write-buffered *(ebp+0x10) "fn ")
19576     8b/-> *(ebp+0xc) 0/r32/eax
19577     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19578     (write-buffered *(ebp+0x10) %eax)
19579     (write-buffered *(ebp+0x10) ": stmt address: output '")
19580     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19581     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19582     (write-buffered *(ebp+0x10) %eax)
19583     (write-buffered *(ebp+0x10) "' not in a register\n")
19584     (flush *(ebp+0x10))
19585     (stop *(ebp+0x14) 1)
19586     # never gets here
19587 
19588 $check-mu-address-stmt:error-too-many-outputs:
19589     (write-buffered *(ebp+0x10) "fn ")
19590     8b/-> *(ebp+0xc) 0/r32/eax
19591     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19592     (write-buffered *(ebp+0x10) %eax)
19593     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
19594     (flush *(ebp+0x10))
19595     (stop *(ebp+0x14) 1)
19596     # never gets here
19597 
19598 $check-mu-address-stmt:error-output-not-address:
19599     (write-buffered *(ebp+0x10) "fn ")
19600     8b/-> *(ebp+0xc) 0/r32/eax
19601     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19602     (write-buffered *(ebp+0x10) %eax)
19603     (write-buffered *(ebp+0x10) ": stmt address: output '")
19604     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19605     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19606     (write-buffered *(ebp+0x10) %eax)
19607     (write-buffered *(ebp+0x10) "' is not an addr\n")
19608     (flush *(ebp+0x10))
19609     (stop *(ebp+0x14) 1)
19610     # never gets here
19611 
19612 $check-mu-address-stmt:error-type-mismatch:
19613     (write-buffered *(ebp+0x10) "fn ")
19614     8b/-> *(ebp+0xc) 0/r32/eax
19615     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19616     (write-buffered *(ebp+0x10) %eax)
19617     (write-buffered *(ebp+0x10) ": stmt address: output '")
19618     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19619     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19620     (write-buffered *(ebp+0x10) %eax)
19621     (write-buffered *(ebp+0x10) "' cannot hold address of '")
19622     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19623     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19624     (write-buffered *(ebp+0x10) %eax)
19625     (write-buffered *(ebp+0x10) "'\n")
19626     (flush *(ebp+0x10))
19627     (stop *(ebp+0x14) 1)
19628     # never gets here
19629 
19630 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
19631     # . prologue
19632     55/push-ebp
19633     89/<- %ebp 4/r32/esp
19634     # . save registers
19635     51/push-ecx
19636     52/push-edx
19637     53/push-ebx
19638     # var curr-a/ecx: (addr type-tree) = a
19639     8b/-> *(ebp+8) 1/r32/ecx
19640     # var curr-b/ebx: (addr type-tree) = b
19641     8b/-> *(ebp+0xc) 3/r32/ebx
19642     # if (curr-a->is-atom?) fall back to regular equality
19643     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19644     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
19645     # if (curr-a->left != curr-b->left) return false
19646     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19647     89/<- %edx 0/r32/eax
19648     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
19649     (type-equal? %edx %eax)  # => eax
19650     3d/compare-eax-and 0/imm32/false
19651     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
19652     # if (curr-a->left == "array") curr-a = curr-a->element-type
19653     {
19654       (is-mu-array? %edx)  # => eax
19655       3d/compare-eax-and 0/imm32/false
19656       75/jump-if-!= break/disp8
19657 $type-equal-ignoring-capacity?:array:
19658       # curr-a = curr-a->right->left
19659       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19660       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19661       89/<- %ecx 0/r32/eax
19662       # curr-b = curr-b->right->left
19663       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
19664       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19665       89/<- %ebx 0/r32/eax
19666       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
19667     }
19668     # if (curr-a->left == "stream") curr-a = curr-a->element-type
19669     {
19670       (is-mu-stream? %edx)  # => eax
19671       3d/compare-eax-and 0/imm32/false
19672       75/jump-if-!= break/disp8
19673 $type-equal-ignoring-capacity?:stream:
19674       # curr-a = curr-a->right->left
19675       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19676       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19677       89/<- %ecx 0/r32/eax
19678       # curr-b = curr-b->right->left
19679       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
19680       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19681       89/<- %ebx 0/r32/eax
19682       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
19683     }
19684 $type-equal-ignoring-capacity?:base-case:
19685     # return type-equal?(curr-a, curr-b)
19686     (type-equal? %ecx %ebx)  # => eax
19687 $type-equal-ignoring-capacity?:end:
19688     # . restore registers
19689     5b/pop-to-ebx
19690     5a/pop-to-edx
19691     59/pop-to-ecx
19692     # . epilogue
19693     89/<- %esp 5/r32/ebp
19694     5d/pop-to-ebp
19695     c3/return
19696 
19697 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19698     # . prologue
19699     55/push-ebp
19700     89/<- %ebp 4/r32/esp
19701     # . save registers
19702     50/push-eax
19703     51/push-ecx
19704     52/push-edx
19705     53/push-ebx
19706     56/push-esi
19707     57/push-edi
19708     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
19709     81 5/subop/subtract %esp 0x60/imm32
19710     68/push 0x60/imm32/size
19711     68/push 0/imm32/read
19712     68/push 0/imm32/write
19713     89/<- %edx 4/r32/esp
19714     # var template/esi: (addr list var) = fn->outputs
19715     8b/-> *(ebp+0xc) 0/r32/eax
19716     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
19717     89/<- %esi 0/r32/eax
19718     # var curr-template/ebx: (addr list var) = fn->outputs
19719     89/<- %ebx 0/r32/eax
19720     # var curr/edi: (addr stmt-var) = stmt->inouts
19721     8b/-> *(ebp+8) 0/r32/eax
19722     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19723     89/<- %edi 0/r32/eax
19724     {
19725       # if template is null, break
19726       81 7/subop/compare %ebx 0/imm32
19727       0f 84/jump-if-= break/disp32
19728       # if curr is null, abort
19729       81 7/subop/compare %edi 0/imm32
19730       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
19731       # var template-type/ecx: (addr type-tree) = template->value->type
19732       (lookup *ebx *(ebx+4))  # List-value List-value => eax
19733       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19734       89/<- %ecx 0/r32/eax
19735       # var curr-type/eax: (addr type-tree) = curr->value->type
19736       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19737       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19738       # if (curr->is-deref?) curr-type = payload of curr-type
19739       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
19740       {
19741         74/jump-if-= break/disp8
19742         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
19743         # if t->right is null, t = t->left
19744         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19745         75/jump-if-!= break/disp8
19746         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19747       }
19748       # if (curr-type != template-type) abort
19749       (type-match? %ecx %eax %edx)  # => eax
19750       3d/compare-eax-and 0/imm32/false
19751       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
19752       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
19753       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
19754       3d/compare-eax-and 0/imm32/false
19755       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
19756       # template = template->next
19757       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
19758       89/<- %ebx 0/r32/eax
19759       # curr = curr->next
19760       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19761       89/<- %edi 0/r32/eax
19762       #
19763       e9/jump loop/disp32
19764     }
19765     # if curr is not null, abort
19766     81 7/subop/compare %edi 0/imm32
19767     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
19768 $check-mu-return-stmt:end:
19769     # . reclaim locals
19770     81 0/subop/add %esp 0x6c/imm32
19771     # . restore registers
19772     5f/pop-to-edi
19773     5e/pop-to-esi
19774     5b/pop-to-ebx
19775     5a/pop-to-edx
19776     59/pop-to-ecx
19777     58/pop-to-eax
19778     # . epilogue
19779     89/<- %esp 5/r32/ebp
19780     5d/pop-to-ebp
19781     c3/return
19782 
19783 $check-mu-return-stmt:error1:
19784     (write-buffered *(ebp+0x10) "fn ")
19785     8b/-> *(ebp+0xc) 0/r32/eax
19786     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19787     (write-buffered *(ebp+0x10) %eax)
19788     (write-buffered *(ebp+0x10) ": return: '")
19789     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19790     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19791     (write-buffered *(ebp+0x10) %eax)
19792     (write-buffered *(ebp+0x10) "' has the wrong type\n")
19793     (flush *(ebp+0x10))
19794     (stop *(ebp+0x14) 1)
19795     # never gets here
19796 
19797 $check-mu-return-stmt:error2:
19798     (write-buffered *(ebp+0x10) "fn ")
19799     8b/-> *(ebp+0xc) 0/r32/eax
19800     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19801     (write-buffered *(ebp+0x10) %eax)
19802     (write-buffered *(ebp+0x10) ": return: '")
19803     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19804     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19805     (write-buffered *(ebp+0x10) %eax)
19806     (write-buffered *(ebp+0x10) "' is no longer available\n")
19807     (flush *(ebp+0x10))
19808     (stop *(ebp+0x14) 1)
19809     # never gets here
19810 
19811 $check-mu-return-stmt:error-too-few-inouts:
19812     (write-buffered *(ebp+0x10) "fn ")
19813     8b/-> *(ebp+0xc) 0/r32/eax
19814     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19815     (write-buffered *(ebp+0x10) %eax)
19816     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
19817     (flush *(ebp+0x10))
19818     (stop *(ebp+0x14) 1)
19819     # never gets here
19820 
19821 $check-mu-return-stmt:error-too-many-inouts:
19822     (write-buffered *(ebp+0x10) "fn ")
19823     8b/-> *(ebp+0xc) 0/r32/eax
19824     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19825     (write-buffered *(ebp+0x10) %eax)
19826     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
19827     (flush *(ebp+0x10))
19828     (stop *(ebp+0x14) 1)
19829     # never gets here
19830 
19831 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19832     # . prologue
19833     55/push-ebp
19834     89/<- %ebp 4/r32/esp
19835     # . save registers
19836     50/push-eax
19837     51/push-ecx
19838     56/push-esi
19839     # var table/esi: (addr table (handle array byte) int 8)
19840     81 5/subop/subtract %esp 0x60/imm32
19841     68/push 0x60/imm32/size
19842     68/push 0/imm32/read
19843     68/push 0/imm32/write
19844     89/<- %esi 4/r32/esp
19845     # var curr/ecx: (addr list var) = outputs
19846     8b/-> *(ebp+8) 1/r32/ecx
19847     {
19848       # if (curr == 0) break
19849       81 7/subop/compare %ecx 0/imm32
19850       0f 84/jump-if-= break/disp32
19851       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
19852       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19853       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19854       # if reg exists in table, abort
19855       (maybe-get %esi %eax 0xc)  # => eax
19856       3d/compare-eax-and 0/imm32
19857       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
19858       # insert reg in table
19859       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19860       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19861       (get-or-insert %esi %eax 0xc Heap)
19862       # curr = curr->next
19863       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
19864       89/<- %ecx 0/r32/eax
19865       e9/jump loop/disp32
19866     }
19867 $check-all-unique-registers:end:
19868     # . reclaim locals
19869     81 0/subop/add %esp 0x6c/imm32
19870     # . restore registers
19871     5e/pop-to-esi
19872     59/pop-to-ecx
19873     58/pop-to-eax
19874     # . epilogue
19875     89/<- %esp 5/r32/ebp
19876     5d/pop-to-ebp
19877     c3/return
19878 
19879 $check-all-unique-registers:abort:
19880     (write-buffered *(ebp+0x10) "fn ")
19881     8b/-> *(ebp+0xc) 0/r32/eax
19882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19883     (write-buffered *(ebp+0x10) %eax)
19884     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
19885     (flush *(ebp+0x10))
19886     (stop *(ebp+0x14) 1)
19887     # never gets here
19888 
19889 # return false if s's register is not between start (inclusive) and end (exclusive)
19890 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
19891 # otherwise return true
19892 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
19893     # . prologue
19894     55/push-ebp
19895     89/<- %ebp 4/r32/esp
19896     # . save registers
19897     51/push-ecx
19898     52/push-edx
19899     53/push-ebx
19900     56/push-esi
19901     57/push-edi
19902     # var target/ebx: (addr array byte) = s->value->register
19903     8b/-> *(ebp+8) 0/r32/eax
19904     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19905     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19906 #?     (write-buffered Stderr "AA: ")
19907 #?     (write-buffered Stderr %eax)
19908 #?     (write-buffered Stderr Newline)
19909 #?     (flush Stderr)
19910     # if (var->register == 0) return false
19911     3d/compare-eax-and 0/imm32
19912     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
19913     89/<- %ebx 0/r32/eax
19914     # var curr/ecx: (addr list var) = start
19915     8b/-> *(ebp+0xc) 1/r32/ecx
19916     # edx = end
19917     8b/-> *(ebp+0x10) 2/r32/edx
19918     {
19919       # if (curr == 0) break
19920       81 7/subop/compare %edi 0/imm32
19921       0f 84/jump-if-= break/disp32
19922       # if (curr == end) break
19923       39/compare %ecx 2/r32/edx
19924       0f 84/jump-if-= break/disp32
19925       # var curr-reg/eax: (addr array byte) = curr->value->register
19926       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19927       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19928       # if (curr-reg == 0) continue
19929       3d/compare-eax-and 0/imm32
19930       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
19931       # if (curr-reg == target) check for conflict
19932       (string-equal? %eax %ebx)  # => eax
19933       3d/compare-eax-and 0/imm32/false
19934       {
19935         74/jump-if-= break/disp8
19936 #?         (write-buffered Stderr "conflict?\n")
19937 #?         (flush Stderr)
19938         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
19939         8b/-> *(ebp+0x14) 0/r32/eax
19940         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19941         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
19942         eb/jump $register-within-list-with-conflict?:end/disp8
19943       }
19944 $register-within-list-with-conflict?:continue:
19945       # curr = curr->next
19946       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
19947       89/<- %ecx 0/r32/eax
19948       e9/jump loop/disp32
19949     }
19950     # return false
19951     b8/copy-to-eax 0/imm32/false
19952 $register-within-list-with-conflict?:end:
19953     # . restore registers
19954     5f/pop-to-edi
19955     5e/pop-to-esi
19956     5b/pop-to-ebx
19957     5a/pop-to-edx
19958     59/pop-to-ecx
19959     # . epilogue
19960     89/<- %esp 5/r32/ebp
19961     5d/pop-to-ebp
19962     c3/return
19963 
19964 # At the first occurrence of register 'reg' in fn-outputs,
19965 # check if the corresponding element of return-inouts has a different register.
19966 # This hacky helper is intended to be called in one specific place. Don't
19967 # reuse it as is.
19968 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
19969     # . prologue
19970     55/push-ebp
19971     89/<- %ebp 4/r32/esp
19972     # . save registers
19973     51/push-ecx
19974     52/push-edx
19975     53/push-ebx
19976     56/push-esi
19977     57/push-edi
19978 #?     (write-buffered Stderr "BB: ")
19979 #?     (write-buffered Stderr *(ebp+8))
19980 #?     (write-buffered Stderr Newline)
19981 #?     (flush Stderr)
19982     # var curr-output/edi: (addr list var) = fn-outputs
19983     8b/-> *(ebp+0x10) 7/r32/edi
19984     # var curr-inout/esi: (addr stmt-var) = return-inouts
19985     8b/-> *(ebp+0xc) 6/r32/esi
19986     {
19987       # if (curr-output == 0) abort
19988       81 7/subop/compare %edi 0/imm32
19989       0f 84/jump-if-= break/disp32
19990       # if (curr-output->value->register != reg) continue
19991       (lookup *edi *(edi+4))  # List-value List-value => eax
19992       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19993       (string-equal? %eax *(ebp+8))  # => eax
19994       3d/compare-eax-and 0/imm32/false
19995       0f 84/jump-if= $register-conflict?:continue/disp32
19996 #?       (write-buffered Stderr "rescan\n")
19997 #?       (flush Stderr)
19998       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
19999       (lookup *esi *(esi+4))  # List-value List-value => eax
20000       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20001       # if (curr-reg == 0) return true
20002       3d/compare-eax-and 0/imm32
20003       {
20004         75/jump-if-!= break/disp8
20005 #?         (write-buffered Stderr "no register\n")
20006 #?         (flush Stderr)
20007         b8/copy-to-eax 1/imm32/true
20008         e9/jump $register-conflict?:end/disp32
20009       }
20010       # return (curr-reg != reg)
20011       (string-equal? %eax *(ebp+8))  # => eax
20012       3d/compare-eax-and 0/imm32/false
20013       0f 94/set-if-= %al
20014 #?       (write-buffered Stderr "final: ")
20015 #?       (write-int32-hex-buffered Stderr %eax)
20016 #?       (write-buffered Stderr Newline)
20017 #?       (flush Stderr)
20018       eb/jump $register-conflict?:end/disp8
20019 $register-conflict?:continue:
20020       # curr-output = curr-output->next
20021       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
20022       89/<- %edi 0/r32/eax
20023       # curr-inout = curr-inout->next
20024       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20025       89/<- %esi 0/r32/eax
20026       e9/jump loop/disp32
20027     }
20028     # should never get here
20029     (write-buffered Stderr "register-conflict? misused\n")
20030     (flush Stderr)
20031     e8/call syscall_exit/disp32
20032 $register-conflict?:end:
20033     # . restore registers
20034     5f/pop-to-edi
20035     5e/pop-to-esi
20036     5b/pop-to-ebx
20037     5a/pop-to-edx
20038     59/pop-to-ecx
20039     # . epilogue
20040     89/<- %esp 5/r32/ebp
20041     5d/pop-to-ebp
20042     c3/return
20043 
20044 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20045     # . prologue
20046     55/push-ebp
20047     89/<- %ebp 4/r32/esp
20048     # . save registers
20049     50/push-eax
20050     51/push-ecx
20051     # var curr/ecx: (addr list stmt) = block->stmts
20052     8b/-> *(ebp+8) 0/r32/eax
20053     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
20054     3d/compare-eax-and 0/imm32
20055     74/jump-if-= $check-final-stmt-is-return:end/disp8
20056     89/<- %ecx 0/r32/eax
20057     {
20058       # if curr->next == 0, break
20059       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20060       3d/compare-eax-and 0/imm32
20061       74/jump-if-= break/disp8
20062       # curr = curr->next
20063       89/<- %ecx 0/r32/eax
20064       e9/jump loop/disp32
20065     }
20066 $check-final-stmt-is-return:check-tag:
20067     # if curr->value->tag != Stmt1, abort
20068     (lookup *ecx *(ecx+4))  # List-value List-value => eax
20069     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
20070     75/jump-if-!= $check-final-stmt-is-return:error/disp8
20071 $check-final-stmt-is-return:check-operation:
20072     # if curr->operation != "return", abort
20073     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20074     (string-equal? %eax "return")
20075     3d/compare-eax-and 0/imm32/false
20076     74/jump-if-= $check-final-stmt-is-return:error/disp8
20077 $check-final-stmt-is-return:end:
20078     # . restore registers
20079     59/pop-to-ecx
20080     58/pop-to-eax
20081     # . epilogue
20082     89/<- %esp 5/r32/ebp
20083     5d/pop-to-ebp
20084     c3/return
20085 
20086 $check-final-stmt-is-return:error:
20087     (write-buffered *(ebp+0x10) "fn ")
20088     8b/-> *(ebp+0xc) 0/r32/eax
20089     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20090     (write-buffered *(ebp+0x10) %eax)
20091     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
20092     (flush *(ebp+0x10))
20093     (stop *(ebp+0x14) 1)
20094     # never gets here
20095 
20096 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20097     # . prologue
20098     55/push-ebp
20099     89/<- %ebp 4/r32/esp
20100     # . save registers
20101     50/push-eax
20102     51/push-ecx
20103     # var curr/ecx: (addr list stmt) = block->stmts
20104     8b/-> *(ebp+8) 0/r32/eax
20105     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
20106     3d/compare-eax-and 0/imm32
20107     0f 84/jump-if-= $check-no-breaks:end/disp32
20108     89/<- %ecx 0/r32/eax
20109     {
20110       # if curr->next == 0, break
20111       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20112       3d/compare-eax-and 0/imm32
20113       74/jump-if-= break/disp8
20114       # if curr->value->tag != Stmt1, continue
20115       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20116       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
20117       75/jump-if-!= $check-no-breaks:continue/disp8
20118       # if curr->value->operation starts with "break", abort
20119       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20120       (string-starts-with? %eax "break")  # => eax
20121       3d/compare-eax-and 0/imm32/false
20122       75/jump-if-!= $check-no-breaks:error/disp8
20123 $check-no-breaks:continue:
20124       # curr = curr->next
20125       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20126       89/<- %ecx 0/r32/eax
20127       e9/jump loop/disp32
20128     }
20129 $check-no-breaks:end:
20130     # . restore registers
20131     59/pop-to-ecx
20132     58/pop-to-eax
20133     # . epilogue
20134     89/<- %esp 5/r32/ebp
20135     5d/pop-to-ebp
20136     c3/return
20137 
20138 $check-no-breaks:error:
20139     (write-buffered *(ebp+0x10) "fn ")
20140     8b/-> *(ebp+0xc) 0/r32/eax
20141     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20142     (write-buffered *(ebp+0x10) %eax)
20143     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
20144     (flush *(ebp+0x10))
20145     (stop *(ebp+0x14) 1)
20146     # never gets here
20147 
20148 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20149     # . prologue
20150     55/push-ebp
20151     89/<- %ebp 4/r32/esp
20152     # . save registers
20153     50/push-eax
20154     51/push-ecx
20155     52/push-edx
20156     53/push-ebx
20157     56/push-esi
20158     57/push-edi
20159     # esi = stmt
20160     8b/-> *(ebp+8) 6/r32/esi
20161     # - check for 0 inouts
20162     # var base/ecx: (addr var) = stmt->inouts->value
20163     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20164     3d/compare-eax-and 0/imm32/false
20165     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
20166     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20167     89/<- %ecx 0/r32/eax
20168 $check-mu-get-stmt:check-base:
20169     # - check base type
20170     # if it's an 'addr', check that it's in a register
20171     # var base-type/ebx: (addr type-tree) = lookup(base->type)
20172     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20173     89/<- %ebx 0/r32/eax
20174     {
20175       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
20176       0f 85/jump-if-!= break/disp32
20177 $check-mu-get-stmt:base-is-compound:
20178       # if (type->left != addr) break
20179       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20180       (is-simple-mu-type? %eax 2)  # addr => eax
20181       3d/compare-eax-and 0/imm32/false
20182       74/jump-if-= break/disp8
20183 $check-mu-get-stmt:base-is-addr:
20184       # now check for register
20185       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20186       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
20187 $check-mu-get-stmt:base-is-addr-in-register:
20188       # type->left is now an addr; skip it
20189       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20190       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20191       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
20192 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
20193       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20194       89/<- %ebx 0/r32/eax
20195     }
20196 $check-mu-get-stmt:check-base-typeinfo:
20197     # ensure type is a container
20198     # var base-type-id/ebx: type-id = base-type->value
20199     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
20200     (is-container? %ebx)  # => eax
20201     3d/compare-eax-and 0/imm32/false
20202     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
20203     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
20204     # . var container/ecx: (handle typeinfo)
20205     68/push 0/imm32
20206     68/push 0/imm32
20207     89/<- %ecx 4/r32/esp
20208     # .
20209     (find-typeinfo %ebx %ecx)
20210     (lookup *ecx *(ecx+4))  # => eax
20211     # . reclaim container
20212     81 0/subop/add %esp 8/imm32
20213     # .
20214     89/<- %edx 0/r32/eax
20215     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
20216     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20217     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20218     89/<- %ecx 0/r32/eax
20219     # - check for 1 inout
20220     3d/compare-eax-and 0/imm32/false
20221     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
20222     # var offset/ecx: (addr var) = lookup(offset->value)
20223     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
20224     89/<- %ecx 0/r32/eax
20225     # - check for valid field
20226     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
20227     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
20228     # - check for too many inouts
20229     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20230     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20231     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20232     3d/compare-eax-and 0/imm32/false
20233     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
20234     # var output/edi: (addr var) = stmt->outputs->value
20235     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20236     # - check for 0 outputs
20237     3d/compare-eax-and 0/imm32/false
20238     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
20239     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20240     89/<- %edi 0/r32/eax
20241 $check-mu-get-stmt:check-output-type:
20242     # - check output type
20243     # must be in register
20244     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
20245     3d/compare-eax-and 0/imm32
20246     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
20247     # must have a non-atomic type
20248     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
20249     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20250     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
20251     # type must start with (addr ...)
20252     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20253     (is-simple-mu-type? %eax 2)  # => eax
20254     3d/compare-eax-and 0/imm32/false
20255     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
20256 $check-mu-get-stmt:check-output-type-match:
20257     # payload of addr type must match 'type' definition
20258     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
20259     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20260     # if (payload->right == null) payload = payload->left
20261     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
20262     {
20263       75/jump-if-!= break/disp8
20264       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20265     }
20266     89/<- %edi 0/r32/eax
20267     # . var output-name/ecx: (addr array byte)
20268     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20269     89/<- %ecx 0/r32/eax
20270     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
20271     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
20272     (get %eax %ecx 0x10)  # => eax
20273     # .
20274     (lookup *eax *(eax+4))  # => eax
20275     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20276     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20277     # .
20278     (type-equal? %edi %eax)  # => eax
20279     3d/compare-eax-and 0/imm32/false
20280     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
20281     # - check for too many outputs
20282     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20283     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20284     3d/compare-eax-and 0/imm32/false
20285     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
20286 $check-mu-get-stmt:end:
20287     # . restore registers
20288     5f/pop-to-edi
20289     5e/pop-to-esi
20290     5b/pop-to-ebx
20291     5a/pop-to-edx
20292     59/pop-to-ecx
20293     58/pop-to-eax
20294     # . epilogue
20295     89/<- %esp 5/r32/ebp
20296     5d/pop-to-ebp
20297     c3/return
20298 
20299 $check-mu-get-stmt:error-too-few-inouts:
20300     (write-buffered *(ebp+0x10) "fn ")
20301     8b/-> *(ebp+0xc) 0/r32/eax
20302     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20303     (write-buffered *(ebp+0x10) %eax)
20304     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
20305     (flush *(ebp+0x10))
20306     (stop *(ebp+0x14) 1)
20307     # never gets here
20308 
20309 $check-mu-get-stmt:error-too-many-inouts:
20310     (write-buffered *(ebp+0x10) "fn ")
20311     8b/-> *(ebp+0xc) 0/r32/eax
20312     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20313     (write-buffered *(ebp+0x10) %eax)
20314     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
20315     (flush *(ebp+0x10))
20316     (stop *(ebp+0x14) 1)
20317     # never gets here
20318 
20319 $check-mu-get-stmt:error-too-few-outputs:
20320     (write-buffered *(ebp+0x10) "fn ")
20321     8b/-> *(ebp+0xc) 0/r32/eax
20322     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20323     (write-buffered *(ebp+0x10) %eax)
20324     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
20325     (flush *(ebp+0x10))
20326     (stop *(ebp+0x14) 1)
20327     # never gets here
20328 
20329 $check-mu-get-stmt:error-too-many-outputs:
20330     (write-buffered *(ebp+0x10) "fn ")
20331     8b/-> *(ebp+0xc) 0/r32/eax
20332     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20333     (write-buffered *(ebp+0x10) %eax)
20334     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
20335     (flush *(ebp+0x10))
20336     (stop *(ebp+0x14) 1)
20337     # never gets here
20338 
20339 $check-mu-get-stmt:error-bad-base:
20340     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
20341     (write-buffered *(ebp+0x10) "fn ")
20342     8b/-> *(ebp+0xc) 0/r32/eax
20343     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20344     (write-buffered *(ebp+0x10) %eax)
20345     (write-buffered *(ebp+0x10) ": stmt get: var '")
20346     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20347     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20348     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20349     (write-buffered *(ebp+0x10) %eax)
20350     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
20351     (flush *(ebp+0x10))
20352     (stop *(ebp+0x14) 1)
20353     # never gets here
20354 
20355 $check-mu-get-stmt:error-base-type-addr-but-not-register:
20356     (write-buffered *(ebp+0x10) "fn ")
20357     8b/-> *(ebp+0xc) 0/r32/eax
20358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20359     (write-buffered *(ebp+0x10) %eax)
20360     (write-buffered *(ebp+0x10) ": stmt get: var '")
20361     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20362     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20363     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20364     (write-buffered *(ebp+0x10) %eax)
20365     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
20366     (flush *(ebp+0x10))
20367     (stop *(ebp+0x14) 1)
20368     # never gets here
20369 
20370 $check-mu-get-stmt:error-bad-field:
20371     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
20372     (write-buffered *(ebp+0x10) "fn ")
20373     8b/-> *(ebp+0xc) 0/r32/eax
20374     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20375     (write-buffered *(ebp+0x10) %eax)
20376     (write-buffered *(ebp+0x10) ": stmt get: type '")
20377     # . write(Type-id->data[tmp])
20378     bf/copy-to-edi Type-id/imm32
20379     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
20380     # .
20381     (write-buffered *(ebp+0x10) "' has no member called '")
20382     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20383     (write-buffered *(ebp+0x10) %eax)
20384     (write-buffered *(ebp+0x10) "'\n")
20385     (flush *(ebp+0x10))
20386     (stop *(ebp+0x14) 1)
20387     # never gets here
20388 
20389 $check-mu-get-stmt:error-output-not-in-register:
20390     (write-buffered *(ebp+0x10) "fn ")
20391     8b/-> *(ebp+0xc) 0/r32/eax
20392     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20393     (write-buffered *(ebp+0x10) %eax)
20394     (write-buffered *(ebp+0x10) ": stmt get: output '")
20395     (lookup *edi *(edi+4))  # Var-name Var-name => eax
20396     (write-buffered *(ebp+0x10) %eax)
20397     (write-buffered *(ebp+0x10) "' is not in a register\n")
20398     (flush *(ebp+0x10))
20399     (stop *(ebp+0x14) 1)
20400     # never gets here
20401 
20402 $check-mu-get-stmt:error-output-type-not-address:
20403     (write-buffered *(ebp+0x10) "fn ")
20404     8b/-> *(ebp+0xc) 0/r32/eax
20405     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20406     (write-buffered *(ebp+0x10) %eax)
20407     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
20408     (flush *(ebp+0x10))
20409     (stop *(ebp+0x14) 1)
20410     # never gets here
20411 
20412 $check-mu-get-stmt:error-bad-output-type:
20413     (write-buffered *(ebp+0x10) "fn ")
20414     8b/-> *(ebp+0xc) 0/r32/eax
20415     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20416     (write-buffered *(ebp+0x10) %eax)
20417     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
20418     (write-buffered *(ebp+0x10) %ecx)
20419     (write-buffered *(ebp+0x10) "' of type '")
20420     bf/copy-to-edi Type-id/imm32
20421     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
20422     (write-buffered *(ebp+0x10) "'\n")
20423     (flush *(ebp+0x10))
20424     (stop *(ebp+0x14) 1)
20425     # never gets here
20426 
20427 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20428     # . prologue
20429     55/push-ebp
20430     89/<- %ebp 4/r32/esp
20431     # . save registers
20432     50/push-eax
20433     51/push-ecx
20434     52/push-edx
20435     53/push-ebx
20436     56/push-esi
20437     57/push-edi
20438     # esi = stmt
20439     8b/-> *(ebp+8) 6/r32/esi
20440     # - check for 0 inouts
20441     # var base/ecx: (addr var) = stmt->inouts->value
20442     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20443 $check-mu-index-stmt:check-no-inouts:
20444     3d/compare-eax-and 0/imm32
20445     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
20446     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20447     89/<- %ecx 0/r32/eax
20448     # - check base type is either (addr array ...) in register or (array ...) on stack
20449     # var base-type/ebx: (addr type-tree) = lookup(base->type)
20450     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20451     89/<- %ebx 0/r32/eax
20452     # if base-type is an atom, abort with a precise error
20453     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
20454     {
20455       74/jump-if-= break/disp8
20456       (is-simple-mu-type? %ebx 3)  # array => eax
20457       3d/compare-eax-and 0/imm32/false
20458       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
20459       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
20460     }
20461 $check-mu-index-stmt:base-is-compound:
20462     # if type->left not addr or array, abort
20463     {
20464       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20465       (is-simple-mu-type? %eax 2)  # addr => eax
20466       3d/compare-eax-and 0/imm32/false
20467       75/jump-if-!= break/disp8
20468       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20469       (is-simple-mu-type? %eax 3)  # array => eax
20470       3d/compare-eax-and 0/imm32/false
20471       75/jump-if-!= break/disp8
20472       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
20473     }
20474     # if (type->left == addr) ensure type->right->left == array and type->register exists
20475     {
20476       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20477       (is-simple-mu-type? %eax 2)  # addr => eax
20478       3d/compare-eax-and 0/imm32/false
20479       74/jump-if-= break/disp8
20480 $check-mu-index-stmt:base-is-addr:
20481       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20482       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20483       (is-simple-mu-type? %eax 3)  # array => eax
20484       3d/compare-eax-and 0/imm32/false
20485       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
20486 $check-mu-index-stmt:check-base-addr-is-register:
20487       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20488       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
20489     }
20490     # if (type->left == array) ensure type->register doesn't exist
20491     {
20492       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20493       (is-simple-mu-type? %eax 3)  # array => eax
20494       3d/compare-eax-and 0/imm32/false
20495       74/jump-if-= break/disp8
20496 $check-mu-index-stmt:base-is-array:
20497       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20498       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
20499     }
20500     # if (base-type->left == addr) base-type = base-type->right
20501     {
20502       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20503       (is-simple-mu-type? %eax 2)  # addr => eax
20504       3d/compare-eax-and 0/imm32/false
20505       74/jump-if-= break/disp8
20506       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20507       89/<- %ebx 0/r32/eax
20508     }
20509     # - check for 1 inout
20510     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
20511     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20512     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20513 $check-mu-index-stmt:check-single-inout:
20514     3d/compare-eax-and 0/imm32
20515     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
20516     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20517     89/<- %ecx 0/r32/eax
20518     # - check index is either a literal or register
20519     # var index-type/edx: (addr type-tree)
20520     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20521     89/<- %edx 0/r32/eax
20522     # if index type is an atom, it must be a literal or int
20523     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
20524     {
20525       74/jump-if-= break/disp8
20526 $check-mu-index-stmt:index-type-is-atom:
20527       (is-simple-mu-type? %edx 0)  # literal => eax
20528       3d/compare-eax-and 0/imm32/false
20529       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
20530       (is-simple-mu-type? %edx 1)  # int => eax
20531       3d/compare-eax-and 0/imm32/false
20532       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
20533       (is-simple-mu-type? %edx 7)  # offset => eax
20534       3d/compare-eax-and 0/imm32/false
20535       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
20536       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
20537     }
20538     # if index type is a non-atom: it must be an offset
20539     {
20540       75/jump-if-!= break/disp8
20541 $check-mu-index-stmt:index-type-is-non-atom:
20542       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
20543       (is-simple-mu-type? %eax 7)  # offset => eax
20544       3d/compare-eax-and 0/imm32/false
20545       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
20546     }
20547 $check-mu-index-stmt:index-type-done:
20548     # check index is either a literal or in a register
20549     {
20550       (is-simple-mu-type? %edx 0)  # literal => eax
20551       3d/compare-eax-and 0/imm32/false
20552       75/jump-if-!= break/disp8
20553 $check-mu-index-stmt:check-index-in-register:
20554       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20555       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
20556     }
20557     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
20558     {
20559       (is-simple-mu-type? %edx 1)  # int => eax
20560       3d/compare-eax-and 0/imm32/false
20561       74/jump-if-= break/disp8
20562 $check-mu-index-stmt:check-index-can-be-int:
20563       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20564       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20565       (array-element-size %eax)  # => eax
20566       3d/compare-eax-and 1/imm32
20567       74/jump-if-= break/disp8
20568       3d/compare-eax-and 2/imm32
20569       74/jump-if-= break/disp8
20570       3d/compare-eax-and 4/imm32
20571       74/jump-if-= break/disp8
20572       3d/compare-eax-and 8/imm32
20573       74/jump-if-= break/disp8
20574       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
20575     }
20576     # - check for too many inouts
20577     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20578     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20579     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20580     3d/compare-eax-and 0/imm32/false
20581     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
20582     # - check for 0 outputs
20583     # var output/edi: (addr var) = stmt->outputs->value
20584     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20585     3d/compare-eax-and 0/imm32/false
20586     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
20587     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20588     89/<- %edi 0/r32/eax
20589     # - check output type
20590     # must have a non-atomic type
20591     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
20592     89/<- %edx 0/r32/eax
20593     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
20594     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
20595     # type must start with (addr ...)
20596     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
20597     (is-simple-mu-type? %eax 2)  # addr => eax
20598     3d/compare-eax-and 0/imm32/false
20599     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
20600     # if tail(base-type) != tail(output-type) abort
20601     (type-tail %ebx)  # => eax
20602     89/<- %ebx 0/r32/eax
20603     (type-tail %edx)  # => eax
20604     (type-equal? %ebx %eax)  # => eax
20605     3d/compare-eax-and 0/imm32/false
20606     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
20607     # - check for too many outputs
20608     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20609     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20610     3d/compare-eax-and 0/imm32/false
20611     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
20612 $check-mu-index-stmt:end:
20613     # . restore registers
20614     5f/pop-to-edi
20615     5e/pop-to-esi
20616     5b/pop-to-ebx
20617     5a/pop-to-edx
20618     59/pop-to-ecx
20619     58/pop-to-eax
20620     # . epilogue
20621     89/<- %esp 5/r32/ebp
20622     5d/pop-to-ebp
20623     c3/return
20624 
20625 $check-mu-index-stmt:error-base-non-array-type:
20626     (write-buffered *(ebp+0x10) "fn ")
20627     8b/-> *(ebp+0xc) 0/r32/eax
20628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20629     (write-buffered *(ebp+0x10) %eax)
20630     (write-buffered *(ebp+0x10) ": stmt index: var '")
20631     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20632     (write-buffered *(ebp+0x10) %eax)
20633     (write-buffered *(ebp+0x10) "' is not an array\n")
20634     (flush *(ebp+0x10))
20635     (stop *(ebp+0x14) 1)
20636     # never gets here
20637 
20638 $check-mu-index-stmt:error-base-array-atom-type:
20639     (write-buffered *(ebp+0x10) "fn ")
20640     8b/-> *(ebp+0xc) 0/r32/eax
20641     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20642     (write-buffered *(ebp+0x10) %eax)
20643     (write-buffered *(ebp+0x10) ": stmt index: array '")
20644     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20645     (write-buffered *(ebp+0x10) %eax)
20646     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
20647     (flush *(ebp+0x10))
20648     (stop *(ebp+0x14) 1)
20649     # never gets here
20650 
20651 $check-mu-index-stmt:error-base-address-array-type-on-stack:
20652     (write-buffered *(ebp+0x10) "fn ")
20653     8b/-> *(ebp+0xc) 0/r32/eax
20654     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20655     (write-buffered *(ebp+0x10) %eax)
20656     (write-buffered *(ebp+0x10) ": stmt index: var '")
20657     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20658     (write-buffered *(ebp+0x10) %eax)
20659     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
20660     (flush *(ebp+0x10))
20661     (stop *(ebp+0x14) 1)
20662     # never gets here
20663 
20664 $check-mu-index-stmt:error-base-array-type-in-register:
20665     (write-buffered *(ebp+0x10) "fn ")
20666     8b/-> *(ebp+0xc) 0/r32/eax
20667     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20668     (write-buffered *(ebp+0x10) %eax)
20669     (write-buffered *(ebp+0x10) ": stmt index: var '")
20670     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20671     (write-buffered *(ebp+0x10) %eax)
20672     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
20673     (flush *(ebp+0x10))
20674     (stop *(ebp+0x14) 1)
20675     # never gets here
20676 
20677 $check-mu-index-stmt:error-too-few-inouts:
20678     (write-buffered *(ebp+0x10) "fn ")
20679     8b/-> *(ebp+0xc) 0/r32/eax
20680     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20681     (write-buffered *(ebp+0x10) %eax)
20682     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
20683     (flush *(ebp+0x10))
20684     (stop *(ebp+0x14) 1)
20685     # never gets here
20686 
20687 $check-mu-index-stmt:error-invalid-index-type:
20688     (write-buffered *(ebp+0x10) "fn ")
20689     8b/-> *(ebp+0xc) 0/r32/eax
20690     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20691     (write-buffered *(ebp+0x10) %eax)
20692     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
20693     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20694     (write-buffered *(ebp+0x10) %eax)
20695     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
20696     (flush *(ebp+0x10))
20697     (stop *(ebp+0x14) 1)
20698     # never gets here
20699 
20700 $check-mu-index-stmt:error-index-offset-atom-type:
20701     (write-buffered *(ebp+0x10) "fn ")
20702     8b/-> *(ebp+0xc) 0/r32/eax
20703     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20704     (write-buffered *(ebp+0x10) %eax)
20705     (write-buffered *(ebp+0x10) ": stmt index: offset '")
20706     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20707     (write-buffered *(ebp+0x10) %eax)
20708     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
20709     (flush *(ebp+0x10))
20710     (stop *(ebp+0x14) 1)
20711     # never gets here
20712 
20713 $check-mu-index-stmt:error-index-on-stack:
20714     (write-buffered *(ebp+0x10) "fn ")
20715     8b/-> *(ebp+0xc) 0/r32/eax
20716     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20717     (write-buffered *(ebp+0x10) %eax)
20718     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
20719     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20720     (write-buffered *(ebp+0x10) %eax)
20721     (write-buffered *(ebp+0x10) "' must be in a register\n")
20722     (flush *(ebp+0x10))
20723     (stop *(ebp+0x14) 1)
20724     # never gets here
20725 
20726 $check-mu-index-stmt:error-index-needs-offset:
20727     (write-buffered *(ebp+0x10) "fn ")
20728     8b/-> *(ebp+0xc) 0/r32/eax
20729     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20730     (write-buffered *(ebp+0x10) %eax)
20731     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
20732     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20733     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20734     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20735     (write-buffered *(ebp+0x10) %eax)
20736     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
20737     (flush *(ebp+0x10))
20738     (stop *(ebp+0x14) 1)
20739     # never gets here
20740 
20741 $check-mu-index-stmt:error-too-many-inouts:
20742     (write-buffered *(ebp+0x10) "fn ")
20743     8b/-> *(ebp+0xc) 0/r32/eax
20744     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20745     (write-buffered *(ebp+0x10) %eax)
20746     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
20747     (flush *(ebp+0x10))
20748     (stop *(ebp+0x14) 1)
20749     # never gets here
20750 
20751 $check-mu-index-stmt:error-too-few-outputs:
20752     (write-buffered *(ebp+0x10) "fn ")
20753     8b/-> *(ebp+0xc) 0/r32/eax
20754     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20755     (write-buffered *(ebp+0x10) %eax)
20756     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
20757     (flush *(ebp+0x10))
20758     (stop *(ebp+0x14) 1)
20759     # never gets here
20760 
20761 $check-mu-index-stmt:error-too-many-outputs:
20762     (write-buffered *(ebp+0x10) "fn ")
20763     8b/-> *(ebp+0xc) 0/r32/eax
20764     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20765     (write-buffered *(ebp+0x10) %eax)
20766     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
20767     (flush *(ebp+0x10))
20768     (stop *(ebp+0x14) 1)
20769     # never gets here
20770 
20771 $check-mu-index-stmt:error-output-not-in-register:
20772     (write-buffered *(ebp+0x10) "fn ")
20773     8b/-> *(ebp+0xc) 0/r32/eax
20774     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20775     (write-buffered *(ebp+0x10) %eax)
20776     (write-buffered *(ebp+0x10) ": stmt index: output '")
20777     (lookup *edi *(edi+4))  # Var-name Var-name => eax
20778     (write-buffered *(ebp+0x10) %eax)
20779     (write-buffered *(ebp+0x10) "' is not in a register\n")
20780     (flush *(ebp+0x10))
20781     (stop *(ebp+0x14) 1)
20782     # never gets here
20783 
20784 $check-mu-index-stmt:error-output-type-not-address:
20785     (write-buffered *(ebp+0x10) "fn ")
20786     8b/-> *(ebp+0xc) 0/r32/eax
20787     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20788     (write-buffered *(ebp+0x10) %eax)
20789     (write-buffered *(ebp+0x10) ": stmt index: output '")
20790     (lookup *edi *(edi+4))  # Var-name Var-name => eax
20791     (write-buffered *(ebp+0x10) %eax)
20792     (write-buffered *(ebp+0x10) "' must be an addr\n")
20793     (flush *(ebp+0x10))
20794     (stop *(ebp+0x14) 1)
20795     # never gets here
20796 
20797 $check-mu-index-stmt:error-bad-output-type:
20798     (write-buffered *(ebp+0x10) "fn ")
20799     8b/-> *(ebp+0xc) 0/r32/eax
20800     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20801     (write-buffered *(ebp+0x10) %eax)
20802     (write-buffered *(ebp+0x10) ": stmt index: output '")
20803     (lookup *edi *(edi+4))  # Var-name Var-name => eax
20804     (write-buffered *(ebp+0x10) %eax)
20805     (write-buffered *(ebp+0x10) "' does not have the right type\n")
20806     (flush *(ebp+0x10))
20807     (stop *(ebp+0x14) 1)
20808     # never gets here
20809 
20810 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20811     # . prologue
20812     55/push-ebp
20813     89/<- %ebp 4/r32/esp
20814     # . save registers
20815     50/push-eax
20816     51/push-ecx
20817     52/push-edx
20818     53/push-ebx
20819     56/push-esi
20820     57/push-edi
20821     # esi = stmt
20822     8b/-> *(ebp+8) 6/r32/esi
20823     # - check for 0 inouts
20824     # var base/ecx: (addr var) = stmt->inouts->value
20825     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20826 $check-mu-length-stmt:check-no-inouts:
20827     3d/compare-eax-and 0/imm32
20828     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
20829     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20830     89/<- %ecx 0/r32/eax
20831     # - check base type is either (addr array ...) in register or (array ...) on stack
20832     # var base-type/ebx: (addr type-tree) = lookup(base->type)
20833     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20834     89/<- %ebx 0/r32/eax
20835     # if base-type is an atom, abort with a precise error
20836     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
20837     {
20838       74/jump-if-= break/disp8
20839       (is-simple-mu-type? %ebx 3)  # array => eax
20840       3d/compare-eax-and 0/imm32/false
20841       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
20842       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
20843     }
20844 $check-mu-length-stmt:base-is-compound:
20845     # if type->left not addr or array, abort
20846     {
20847       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20848       (is-simple-mu-type? %eax 2)  # addr => eax
20849       3d/compare-eax-and 0/imm32/false
20850       75/jump-if-!= break/disp8
20851       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20852       (is-simple-mu-type? %eax 3)  # array => eax
20853       3d/compare-eax-and 0/imm32/false
20854       75/jump-if-!= break/disp8
20855       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
20856     }
20857     # if (type->left == addr) ensure type->right->left == array and type->register exists
20858     {
20859       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20860       (is-simple-mu-type? %eax 2)  # addr => eax
20861       3d/compare-eax-and 0/imm32/false
20862       74/jump-if-= break/disp8
20863 $check-mu-length-stmt:base-is-addr:
20864       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20865       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20866       (is-simple-mu-type? %eax 3)  # array => eax
20867       3d/compare-eax-and 0/imm32/false
20868       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
20869 $check-mu-length-stmt:check-base-addr-is-register:
20870       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20871       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
20872     }
20873     # if (type->left == array) ensure type->register doesn't exist
20874     {
20875       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20876       (is-simple-mu-type? %eax 3)  # array => eax
20877       3d/compare-eax-and 0/imm32/false
20878       74/jump-if-= break/disp8
20879 $check-mu-length-stmt:base-is-array:
20880       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20881       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
20882     }
20883     # if (base-type->left == addr) base-type = base-type->right
20884     {
20885       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20886       (is-simple-mu-type? %eax 2)  # addr => eax
20887       3d/compare-eax-and 0/imm32/false
20888       74/jump-if-= break/disp8
20889       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20890       89/<- %ebx 0/r32/eax
20891     }
20892     # - check for too many inouts
20893     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20894     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20895     3d/compare-eax-and 0/imm32/false
20896     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
20897     # - check for 0 outputs
20898     # var output/edi: (addr var) = stmt->outputs->value
20899     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20900     3d/compare-eax-and 0/imm32/false
20901     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
20902     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20903     89/<- %edi 0/r32/eax
20904     # - check output type
20905     # must have a non-atomic type
20906     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
20907     (is-simple-mu-type? %eax 1)  # int => eax
20908     3d/compare-eax-and 0/imm32/false
20909     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
20910     # - check for too many outputs
20911     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20912     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20913     3d/compare-eax-and 0/imm32/false
20914     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
20915 $check-mu-length-stmt:end:
20916     # . restore registers
20917     5f/pop-to-edi
20918     5e/pop-to-esi
20919     5b/pop-to-ebx
20920     5a/pop-to-edx
20921     59/pop-to-ecx
20922     58/pop-to-eax
20923     # . epilogue
20924     89/<- %esp 5/r32/ebp
20925     5d/pop-to-ebp
20926     c3/return
20927 
20928 $check-mu-length-stmt:error-base-non-array-type:
20929     (write-buffered *(ebp+0x10) "fn ")
20930     8b/-> *(ebp+0xc) 0/r32/eax
20931     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20932     (write-buffered *(ebp+0x10) %eax)
20933     (write-buffered *(ebp+0x10) ": stmt length: var '")
20934     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20935     (write-buffered *(ebp+0x10) %eax)
20936     (write-buffered *(ebp+0x10) "' is not an array\n")
20937     (flush *(ebp+0x10))
20938     (stop *(ebp+0x14) 1)
20939     # never gets here
20940 
20941 $check-mu-length-stmt:error-base-array-atom-type:
20942     (write-buffered *(ebp+0x10) "fn ")
20943     8b/-> *(ebp+0xc) 0/r32/eax
20944     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20945     (write-buffered *(ebp+0x10) %eax)
20946     (write-buffered *(ebp+0x10) ": stmt length: array '")
20947     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20948     (write-buffered *(ebp+0x10) %eax)
20949     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
20950     (flush *(ebp+0x10))
20951     (stop *(ebp+0x14) 1)
20952     # never gets here
20953 
20954 $check-mu-length-stmt:error-base-address-array-type-on-stack:
20955     (write-buffered *(ebp+0x10) "fn ")
20956     8b/-> *(ebp+0xc) 0/r32/eax
20957     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20958     (write-buffered *(ebp+0x10) %eax)
20959     (write-buffered *(ebp+0x10) ": stmt length: var '")
20960     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20961     (write-buffered *(ebp+0x10) %eax)
20962     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
20963     (flush *(ebp+0x10))
20964     (stop *(ebp+0x14) 1)
20965     # never gets here
20966 
20967 $check-mu-length-stmt:error-base-array-type-in-register:
20968     (write-buffered *(ebp+0x10) "fn ")
20969     8b/-> *(ebp+0xc) 0/r32/eax
20970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20971     (write-buffered *(ebp+0x10) %eax)
20972     (write-buffered *(ebp+0x10) ": stmt length: var '")
20973     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20974     (write-buffered *(ebp+0x10) %eax)
20975     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
20976     (flush *(ebp+0x10))
20977     (stop *(ebp+0x14) 1)
20978     # never gets here
20979 
20980 $check-mu-length-stmt:error-too-few-inouts:
20981     (write-buffered *(ebp+0x10) "fn ")
20982     8b/-> *(ebp+0xc) 0/r32/eax
20983     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20984     (write-buffered *(ebp+0x10) %eax)
20985     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
20986     (flush *(ebp+0x10))
20987     (stop *(ebp+0x14) 1)
20988     # never gets here
20989 
20990 $check-mu-length-stmt:error-invalid-index-type:
20991     (write-buffered *(ebp+0x10) "fn ")
20992     8b/-> *(ebp+0xc) 0/r32/eax
20993     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20994     (write-buffered *(ebp+0x10) %eax)
20995     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
20996     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20997     (write-buffered *(ebp+0x10) %eax)
20998     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
20999     (flush *(ebp+0x10))
21000     (stop *(ebp+0x14) 1)
21001     # never gets here
21002 
21003 $check-mu-length-stmt:error-index-offset-atom-type:
21004     (write-buffered *(ebp+0x10) "fn ")
21005     8b/-> *(ebp+0xc) 0/r32/eax
21006     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21007     (write-buffered *(ebp+0x10) %eax)
21008     (write-buffered *(ebp+0x10) ": stmt length: offset '")
21009     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21010     (write-buffered *(ebp+0x10) %eax)
21011     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
21012     (flush *(ebp+0x10))
21013     (stop *(ebp+0x14) 1)
21014     # never gets here
21015 
21016 $check-mu-length-stmt:error-index-on-stack:
21017     (write-buffered *(ebp+0x10) "fn ")
21018     8b/-> *(ebp+0xc) 0/r32/eax
21019     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21020     (write-buffered *(ebp+0x10) %eax)
21021     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
21022     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21023     (write-buffered *(ebp+0x10) %eax)
21024     (write-buffered *(ebp+0x10) "' must be in a register\n")
21025     (flush *(ebp+0x10))
21026     (stop *(ebp+0x14) 1)
21027     # never gets here
21028 
21029 $check-mu-length-stmt:error-index-needs-offset:
21030     (write-buffered *(ebp+0x10) "fn ")
21031     8b/-> *(ebp+0xc) 0/r32/eax
21032     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21033     (write-buffered *(ebp+0x10) %eax)
21034     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
21035     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21036     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21037     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21038     (write-buffered *(ebp+0x10) %eax)
21039     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
21040     (flush *(ebp+0x10))
21041     (stop *(ebp+0x14) 1)
21042     # never gets here
21043 
21044 $check-mu-length-stmt:error-too-many-inouts:
21045     (write-buffered *(ebp+0x10) "fn ")
21046     8b/-> *(ebp+0xc) 0/r32/eax
21047     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21048     (write-buffered *(ebp+0x10) %eax)
21049     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
21050     (flush *(ebp+0x10))
21051     (stop *(ebp+0x14) 1)
21052     # never gets here
21053 
21054 $check-mu-length-stmt:error-too-few-outputs:
21055     (write-buffered *(ebp+0x10) "fn ")
21056     8b/-> *(ebp+0xc) 0/r32/eax
21057     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21058     (write-buffered *(ebp+0x10) %eax)
21059     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
21060     (flush *(ebp+0x10))
21061     (stop *(ebp+0x14) 1)
21062     # never gets here
21063 
21064 $check-mu-length-stmt:error-too-many-outputs:
21065     (write-buffered *(ebp+0x10) "fn ")
21066     8b/-> *(ebp+0xc) 0/r32/eax
21067     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21068     (write-buffered *(ebp+0x10) %eax)
21069     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
21070     (flush *(ebp+0x10))
21071     (stop *(ebp+0x14) 1)
21072     # never gets here
21073 
21074 $check-mu-length-stmt:error-output-not-in-register:
21075     (write-buffered *(ebp+0x10) "fn ")
21076     8b/-> *(ebp+0xc) 0/r32/eax
21077     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21078     (write-buffered *(ebp+0x10) %eax)
21079     (write-buffered *(ebp+0x10) ": stmt length: output '")
21080     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21081     (write-buffered *(ebp+0x10) %eax)
21082     (write-buffered *(ebp+0x10) "' is not in a register\n")
21083     (flush *(ebp+0x10))
21084     (stop *(ebp+0x14) 1)
21085     # never gets here
21086 
21087 $check-mu-length-stmt:error-invalid-output-type:
21088     (write-buffered *(ebp+0x10) "fn ")
21089     8b/-> *(ebp+0xc) 0/r32/eax
21090     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21091     (write-buffered *(ebp+0x10) %eax)
21092     (write-buffered *(ebp+0x10) ": stmt length: output '")
21093     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21094     (write-buffered *(ebp+0x10) %eax)
21095     (write-buffered *(ebp+0x10) "' does not have the right type\n")
21096     (flush *(ebp+0x10))
21097     (stop *(ebp+0x14) 1)
21098     # never gets here
21099 
21100 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21101     # . prologue
21102     55/push-ebp
21103     89/<- %ebp 4/r32/esp
21104     # . save registers
21105     50/push-eax
21106     51/push-ecx
21107     52/push-edx
21108     53/push-ebx
21109     56/push-esi
21110     57/push-edi
21111     # esi = stmt
21112     8b/-> *(ebp+8) 6/r32/esi
21113     # - check for 0 inouts
21114     # var base/ecx: (addr var) = stmt->inouts->value
21115     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21116 $check-mu-compute-offset-stmt:check-no-inouts:
21117     3d/compare-eax-and 0/imm32
21118     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
21119     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21120     89/<- %ecx 0/r32/eax
21121     # - check base type is either (addr array ...) in register or (array ...) on stack
21122     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21123     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21124     89/<- %ebx 0/r32/eax
21125     # if base-type is an atom, abort with a precise error
21126     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21127     {
21128       74/jump-if-= break/disp8
21129       (is-simple-mu-type? %ebx 3)  # array => eax
21130       3d/compare-eax-and 0/imm32/false
21131       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
21132       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
21133     }
21134 $check-mu-compute-offset-stmt:base-is-compound:
21135     # if type->left not addr or array, abort
21136     {
21137       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21138       (is-simple-mu-type? %eax 2)  # addr => eax
21139       3d/compare-eax-and 0/imm32/false
21140       75/jump-if-!= break/disp8
21141       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21142       (is-simple-mu-type? %eax 3)  # array => eax
21143       3d/compare-eax-and 0/imm32/false
21144       75/jump-if-!= break/disp8
21145       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
21146     }
21147     # if (type->left == addr) ensure type->right->left == array and type->register exists
21148     {
21149       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21150       (is-simple-mu-type? %eax 2)  # addr => eax
21151       3d/compare-eax-and 0/imm32/false
21152       74/jump-if-= break/disp8
21153 $check-mu-compute-offset-stmt:base-is-addr:
21154       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21155       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21156       (is-simple-mu-type? %eax 3)  # array => eax
21157       3d/compare-eax-and 0/imm32/false
21158       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
21159     }
21160     # if (base-type->left == addr) base-type = base-type->right
21161     {
21162       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21163       (is-simple-mu-type? %eax 2)  # addr => eax
21164       3d/compare-eax-and 0/imm32/false
21165       74/jump-if-= break/disp8
21166       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21167       89/<- %ebx 0/r32/eax
21168     }
21169     # - check for 1 inout
21170     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
21171     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21172     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21173 $check-mu-compute-offset-stmt:check-single-inout:
21174     3d/compare-eax-and 0/imm32
21175     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
21176     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21177     89/<- %ecx 0/r32/eax
21178     # - check index is either a literal or register
21179     # var index-type/edx: (addr type-tree)
21180     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21181     89/<- %edx 0/r32/eax
21182     # index type must be a literal or int
21183     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21184     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
21185     {
21186 $check-mu-compute-offset-stmt:index-type-is-atom:
21187       (is-simple-mu-type? %edx 0)  # literal => eax
21188       3d/compare-eax-and 0/imm32/false
21189       75/jump-if-!= break/disp8
21190       (is-simple-mu-type? %edx 1)  # int => eax
21191       3d/compare-eax-and 0/imm32/false
21192       75/jump-if-!= break/disp8
21193       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
21194     }
21195     # - check for too many inouts
21196     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21197     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21198     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21199     3d/compare-eax-and 0/imm32/false
21200     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
21201     # - check for 0 outputs
21202     # var output/edi: (addr var) = stmt->outputs->value
21203     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21204     3d/compare-eax-and 0/imm32/false
21205     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
21206     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21207     89/<- %edi 0/r32/eax
21208     # - check output type
21209     # must have a non-atomic type
21210     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21211     89/<- %edx 0/r32/eax
21212     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21213     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
21214     # type must start with (offset ...)
21215     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
21216     (is-simple-mu-type? %eax 7)  # offset => eax
21217     3d/compare-eax-and 0/imm32/false
21218     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
21219     # if tail(base-type) != tail(output-type) abort
21220     (type-tail %ebx)  # => eax
21221     89/<- %ebx 0/r32/eax
21222     (type-tail %edx)  # => eax
21223     (type-equal? %ebx %eax)  # => eax
21224     3d/compare-eax-and 0/imm32/false
21225     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
21226     # - check for too many outputs
21227     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21228     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21229     3d/compare-eax-and 0/imm32/false
21230     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
21231 $check-mu-compute-offset-stmt:end:
21232     # . restore registers
21233     5f/pop-to-edi
21234     5e/pop-to-esi
21235     5b/pop-to-ebx
21236     5a/pop-to-edx
21237     59/pop-to-ecx
21238     58/pop-to-eax
21239     # . epilogue
21240     89/<- %esp 5/r32/ebp
21241     5d/pop-to-ebp
21242     c3/return
21243 
21244 $check-mu-compute-offset-stmt:error-base-non-array-type:
21245     (write-buffered *(ebp+0x10) "fn ")
21246     8b/-> *(ebp+0xc) 0/r32/eax
21247     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21248     (write-buffered *(ebp+0x10) %eax)
21249     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
21250     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21251     (write-buffered *(ebp+0x10) %eax)
21252     (write-buffered *(ebp+0x10) "' is not an array\n")
21253     (flush *(ebp+0x10))
21254     (stop *(ebp+0x14) 1)
21255     # never gets here
21256 
21257 $check-mu-compute-offset-stmt:error-base-array-atom-type:
21258     (write-buffered *(ebp+0x10) "fn ")
21259     8b/-> *(ebp+0xc) 0/r32/eax
21260     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21261     (write-buffered *(ebp+0x10) %eax)
21262     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
21263     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21264     (write-buffered *(ebp+0x10) %eax)
21265     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
21266     (flush *(ebp+0x10))
21267     (stop *(ebp+0x14) 1)
21268     # never gets here
21269 
21270 $check-mu-compute-offset-stmt:error-too-few-inouts:
21271     (write-buffered *(ebp+0x10) "fn ")
21272     8b/-> *(ebp+0xc) 0/r32/eax
21273     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21274     (write-buffered *(ebp+0x10) %eax)
21275     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
21276     (flush *(ebp+0x10))
21277     (stop *(ebp+0x14) 1)
21278     # never gets here
21279 
21280 $check-mu-compute-offset-stmt:error-invalid-index-type:
21281     (write-buffered *(ebp+0x10) "fn ")
21282     8b/-> *(ebp+0xc) 0/r32/eax
21283     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21284     (write-buffered *(ebp+0x10) %eax)
21285     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
21286     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21287     (write-buffered *(ebp+0x10) %eax)
21288     (write-buffered *(ebp+0x10) "' must be an int\n")
21289     (flush *(ebp+0x10))
21290     (stop *(ebp+0x14) 1)
21291     # never gets here
21292 
21293 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
21294     (write-buffered *(ebp+0x10) "fn ")
21295     8b/-> *(ebp+0xc) 0/r32/eax
21296     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21297     (write-buffered *(ebp+0x10) %eax)
21298     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
21299     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21300     (write-buffered *(ebp+0x10) %eax)
21301     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
21302     (flush *(ebp+0x10))
21303     (stop *(ebp+0x14) 1)
21304     # never gets here
21305 
21306 $check-mu-compute-offset-stmt:error-index-on-stack:
21307     (write-buffered *(ebp+0x10) "fn ")
21308     8b/-> *(ebp+0xc) 0/r32/eax
21309     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21310     (write-buffered *(ebp+0x10) %eax)
21311     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
21312     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21313     (write-buffered *(ebp+0x10) %eax)
21314     (write-buffered *(ebp+0x10) "' must be in a register\n")
21315     (flush *(ebp+0x10))
21316     (stop *(ebp+0x14) 1)
21317     # never gets here
21318 
21319 $check-mu-compute-offset-stmt:error-too-many-inouts:
21320     (write-buffered *(ebp+0x10) "fn ")
21321     8b/-> *(ebp+0xc) 0/r32/eax
21322     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21323     (write-buffered *(ebp+0x10) %eax)
21324     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
21325     (flush *(ebp+0x10))
21326     (stop *(ebp+0x14) 1)
21327     # never gets here
21328 
21329 $check-mu-compute-offset-stmt:error-too-few-outputs:
21330     (write-buffered *(ebp+0x10) "fn ")
21331     8b/-> *(ebp+0xc) 0/r32/eax
21332     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21333     (write-buffered *(ebp+0x10) %eax)
21334     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
21335     (flush *(ebp+0x10))
21336     (stop *(ebp+0x14) 1)
21337     # never gets here
21338 
21339 $check-mu-compute-offset-stmt:error-too-many-outputs:
21340     (write-buffered *(ebp+0x10) "fn ")
21341     8b/-> *(ebp+0xc) 0/r32/eax
21342     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21343     (write-buffered *(ebp+0x10) %eax)
21344     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
21345     (flush *(ebp+0x10))
21346     (stop *(ebp+0x14) 1)
21347     # never gets here
21348 
21349 $check-mu-compute-offset-stmt:error-output-not-in-register:
21350     (write-buffered *(ebp+0x10) "fn ")
21351     8b/-> *(ebp+0xc) 0/r32/eax
21352     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21353     (write-buffered *(ebp+0x10) %eax)
21354     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
21355     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21356     (write-buffered *(ebp+0x10) %eax)
21357     (write-buffered *(ebp+0x10) "' is not in a register\n")
21358     (flush *(ebp+0x10))
21359     (stop *(ebp+0x14) 1)
21360     # never gets here
21361 
21362 $check-mu-compute-offset-stmt:error-output-type-not-offset:
21363     (write-buffered *(ebp+0x10) "fn ")
21364     8b/-> *(ebp+0xc) 0/r32/eax
21365     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21366     (write-buffered *(ebp+0x10) %eax)
21367     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
21368     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21369     (write-buffered *(ebp+0x10) %eax)
21370     (write-buffered *(ebp+0x10) "' must be an offset\n")
21371     (flush *(ebp+0x10))
21372     (stop *(ebp+0x14) 1)
21373     # never gets here
21374 
21375 $check-mu-compute-offset-stmt:error-bad-output-type:
21376     (write-buffered *(ebp+0x10) "fn ")
21377     8b/-> *(ebp+0xc) 0/r32/eax
21378     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21379     (write-buffered *(ebp+0x10) %eax)
21380     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
21381     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21382     (write-buffered *(ebp+0x10) %eax)
21383     (write-buffered *(ebp+0x10) "' does not have the right type\n")
21384     (flush *(ebp+0x10))
21385     (stop *(ebp+0x14) 1)
21386     # never gets here
21387 
21388 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21389     # . prologue
21390     55/push-ebp
21391     89/<- %ebp 4/r32/esp
21392     # . save registers
21393     50/push-eax
21394     51/push-ecx
21395     53/push-ebx
21396     56/push-esi
21397     57/push-edi
21398     # esi = stmt
21399     8b/-> *(ebp+8) 6/r32/esi
21400 $check-mu-copy-object-stmt:check-for-output:
21401     # if stmt->outputs abort
21402     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21403     3d/compare-eax-and 0/imm32
21404     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
21405 $check-mu-copy-object-stmt:get-left:
21406     # var dest/edi: (addr stmt-var) = stmt->inouts
21407     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21408     89/<- %edi 0/r32/eax
21409     # zero inouts
21410     3d/compare-eax-and 0/imm32
21411     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
21412 $check-mu-copy-object-stmt:get-src:
21413     # var src/esi: (addr stmt-var) = dest->next
21414     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21415     89/<- %esi 0/r32/eax
21416     # 1 inout
21417     3d/compare-eax-and 0/imm32
21418     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
21419     # > 2 inouts
21420     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21421     3d/compare-eax-and 0/imm32
21422     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
21423 $check-mu-copy-object-stmt:types:
21424     # var src-type/ecx: (addr type-tree) = src->value->type
21425     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21426     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21427     89/<- %ecx 0/r32/eax
21428     # if (src->is-deref?) src-type = src-type->payload
21429     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
21430     3d/compare-eax-and 0/imm32/false
21431     {
21432       74/jump-if-= break/disp8
21433       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21434       # if src-type->right is null, src-type = src-type->left
21435       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21436       {
21437         75/jump-if-!= break/disp8
21438         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21439       }
21440       89/<- %ecx 0/r32/eax
21441     }
21442     # if src-type is not addr, abort
21443     (is-mu-addr-type? %ecx)  # => eax
21444     3d/compare-eax-and 0/imm32/false
21445     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
21446     # var dest-type/ebx: (addr type-tree) = dest->value->type
21447     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21448     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21449     89/<- %ebx 0/r32/eax
21450     # if (dest->is-deref?) dest-type = dest-type->payload
21451     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
21452     3d/compare-eax-and 0/imm32/false
21453     {
21454       74/jump-if-= break/disp8
21455       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21456       # if dest-type->right is null, dest-type = dest-type->left
21457       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21458       {
21459         75/jump-if-!= break/disp8
21460         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21461       }
21462       89/<- %ebx 0/r32/eax
21463     }
21464     # if (dest-type != src-type) abort
21465     (type-equal? %ecx %ebx)  # => eax
21466     3d/compare-eax-and 0/imm32
21467     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
21468 $check-mu-copy-object-stmt:end:
21469     # . restore registers
21470     5f/pop-to-edi
21471     5e/pop-to-esi
21472     5b/pop-to-ebx
21473     59/pop-to-ecx
21474     58/pop-to-eax
21475     # . epilogue
21476     89/<- %esp 5/r32/ebp
21477     5d/pop-to-ebp
21478     c3/return
21479 
21480 $check-mu-copy-object-stmt:error-incorrect-inouts:
21481     (write-buffered *(ebp+0x10) "fn ")
21482     8b/-> *(ebp+0xc) 0/r32/eax
21483     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21484     (write-buffered *(ebp+0x10) %eax)
21485     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
21486     (flush *(ebp+0x10))
21487     (stop *(ebp+0x14) 1)
21488     # never gets here
21489 
21490 $check-mu-copy-object-stmt:error-too-many-outputs:
21491     (write-buffered *(ebp+0x10) "fn ")
21492     8b/-> *(ebp+0xc) 0/r32/eax
21493     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21494     (write-buffered *(ebp+0x10) %eax)
21495     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
21496     (flush *(ebp+0x10))
21497     (stop *(ebp+0x14) 1)
21498     # never gets here
21499 
21500 $check-mu-copy-object-stmt:error-invalid-types:
21501     (write-buffered *(ebp+0x10) "fn ")
21502     8b/-> *(ebp+0xc) 0/r32/eax
21503     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21504     (write-buffered *(ebp+0x10) %eax)
21505     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
21506     (flush *(ebp+0x10))
21507     (stop *(ebp+0x14) 1)
21508     # never gets here
21509 
21510 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21511     # . prologue
21512     55/push-ebp
21513     89/<- %ebp 4/r32/esp
21514     # . save registers
21515     50/push-eax
21516     53/push-ebx
21517     56/push-esi
21518     57/push-edi
21519     # esi = stmt
21520     8b/-> *(ebp+8) 6/r32/esi
21521 $check-mu-allocate-stmt:check-for-output:
21522     # if stmt->outputs abort
21523     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21524     3d/compare-eax-and 0/imm32
21525     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
21526 $check-mu-allocate-stmt:get-target:
21527     # var target/edi: (addr stmt-var) = stmt->inouts
21528     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21529     89/<- %edi 0/r32/eax
21530     # zero inouts
21531     3d/compare-eax-and 0/imm32
21532     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
21533     # > 1 inouts
21534     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21535     3d/compare-eax-and 0/imm32
21536     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
21537 $check-mu-allocate-stmt:check-type:
21538     # var target-type/ebx: (addr type-tree) = target->value->type
21539     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21540     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21541     89/<- %ebx 0/r32/eax
21542     # if (target->is-deref?) target-type = target-type->payload
21543     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
21544     3d/compare-eax-and 0/imm32/false
21545     {
21546       74/jump-if-= break/disp8
21547       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21548       # if target-type->right is null, target-type = target-type->left
21549       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21550       {
21551         75/jump-if-!= break/disp8
21552         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21553       }
21554       89/<- %ebx 0/r32/eax
21555     }
21556     # if target-type is not addr, abort
21557     (is-mu-addr-type? %ebx)  # => eax
21558     3d/compare-eax-and 0/imm32/false
21559     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
21560     # if target-type->right is an atom, abort
21561     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21562     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21563     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
21564     # if target-type->right->left is not handle, abort
21565     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21566     (is-simple-mu-type? %eax 4)  # handle => eax
21567     3d/compare-eax-and 0/imm32/false
21568     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
21569 $check-mu-allocate-stmt:end:
21570     # . restore registers
21571     5f/pop-to-edi
21572     5e/pop-to-esi
21573     5b/pop-to-ebx
21574     58/pop-to-eax
21575     # . epilogue
21576     89/<- %esp 5/r32/ebp
21577     5d/pop-to-ebp
21578     c3/return
21579 
21580 $check-mu-allocate-stmt:error-incorrect-inouts:
21581     (write-buffered *(ebp+0x10) "fn ")
21582     8b/-> *(ebp+0xc) 0/r32/eax
21583     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21584     (write-buffered *(ebp+0x10) %eax)
21585     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
21586     (flush *(ebp+0x10))
21587     (stop *(ebp+0x14) 1)
21588     # never gets here
21589 
21590 $check-mu-allocate-stmt:error-too-many-outputs:
21591     (write-buffered *(ebp+0x10) "fn ")
21592     8b/-> *(ebp+0xc) 0/r32/eax
21593     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21594     (write-buffered *(ebp+0x10) %eax)
21595     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
21596     (flush *(ebp+0x10))
21597     (stop *(ebp+0x14) 1)
21598     # never gets here
21599 
21600 $check-mu-allocate-stmt:error-invalid-type:
21601     (write-buffered *(ebp+0x10) "fn ")
21602     8b/-> *(ebp+0xc) 0/r32/eax
21603     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21604     (write-buffered *(ebp+0x10) %eax)
21605     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
21606     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21607     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21608     (write-buffered *(ebp+0x10) %eax)
21609     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
21610     (flush *(ebp+0x10))
21611     (stop *(ebp+0x14) 1)
21612     # never gets here
21613 
21614 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21615     # . prologue
21616     55/push-ebp
21617     89/<- %ebp 4/r32/esp
21618     # . save registers
21619     50/push-eax
21620     53/push-ebx
21621     56/push-esi
21622     57/push-edi
21623     # esi = stmt
21624     8b/-> *(ebp+8) 6/r32/esi
21625 $check-mu-populate-stmt:check-for-output:
21626     # if stmt->outputs abort
21627     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21628     3d/compare-eax-and 0/imm32
21629     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
21630 $check-mu-populate-stmt:get-target:
21631     # var target/edi: (addr stmt-var) = stmt->inouts
21632     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21633     89/<- %edi 0/r32/eax
21634     # zero inouts
21635     3d/compare-eax-and 0/imm32
21636     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
21637 $check-mu-populate-stmt:get-length:
21638     # var length/esi: (addr stmt-var) = dest->next
21639     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21640     89/<- %esi 0/r32/eax
21641     # 1 inout
21642     3d/compare-eax-and 0/imm32
21643     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
21644     # > 2 inouts
21645     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21646     3d/compare-eax-and 0/imm32
21647     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
21648 $check-mu-populate-stmt:check-target-type:
21649     # var target-type/ebx: (addr type-tree) = target->value->type
21650     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21651     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21652     89/<- %ebx 0/r32/eax
21653 $check-mu-populate-stmt:check-target-type-deref:
21654     # if (target->is-deref?) target-type = target-type->payload
21655     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
21656     3d/compare-eax-and 0/imm32/false
21657     {
21658       74/jump-if-= break/disp8
21659       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21660       # if target-type->right is null, target-type = target-type->left
21661       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21662       {
21663         75/jump-if-!= break/disp8
21664         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21665       }
21666       89/<- %ebx 0/r32/eax
21667     }
21668 $check-mu-populate-stmt:check-target-type-addr:
21669     # if target-type is not addr, abort
21670     (is-mu-addr-type? %ebx)  # => eax
21671     3d/compare-eax-and 0/imm32/false
21672     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
21673     # if target-type->right is an atom, abort
21674     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21675     89/<- %ebx 0/r32/eax
21676     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21677     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
21678 $check-mu-populate-stmt:check-target-type-handle:
21679     # if target-type->right->left is not handle, abort
21680     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21681     (is-simple-mu-type? %eax 4)  # handle => eax
21682     3d/compare-eax-and 0/imm32/false
21683     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
21684     # if target-type->right->right is an atom, abort
21685     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21686     89/<- %ebx 0/r32/eax
21687     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21688     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
21689 $check-mu-populate-stmt:check-target-type-array:
21690     # if target-type->right->right->left is not array, abort
21691     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21692     (is-simple-mu-type? %eax 3)  # array => eax
21693     3d/compare-eax-and 0/imm32/false
21694     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
21695 $check-mu-populate-stmt:check-length-type:
21696     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21697     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21698     89/<- %ebx 0/r32/eax
21699     (is-simple-mu-type? %ebx 0)  # literal => eax
21700     3d/compare-eax-and 0/imm32/false
21701     75/jump-if-!= $check-mu-populate-stmt:end/disp8
21702     (is-simple-mu-type? %ebx 1)  # int => eax
21703     3d/compare-eax-and 0/imm32/false
21704     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
21705 $check-mu-populate-stmt:end:
21706     # . restore registers
21707     5f/pop-to-edi
21708     5e/pop-to-esi
21709     5b/pop-to-ebx
21710     58/pop-to-eax
21711     # . epilogue
21712     89/<- %esp 5/r32/ebp
21713     5d/pop-to-ebp
21714     c3/return
21715 
21716 $check-mu-populate-stmt:error-incorrect-inouts:
21717     (write-buffered *(ebp+0x10) "fn ")
21718     8b/-> *(ebp+0xc) 0/r32/eax
21719     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21720     (write-buffered *(ebp+0x10) %eax)
21721     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
21722     (flush *(ebp+0x10))
21723     (stop *(ebp+0x14) 1)
21724     # never gets here
21725 
21726 $check-mu-populate-stmt:error-too-many-outputs:
21727     (write-buffered *(ebp+0x10) "fn ")
21728     8b/-> *(ebp+0xc) 0/r32/eax
21729     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21730     (write-buffered *(ebp+0x10) %eax)
21731     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
21732     (flush *(ebp+0x10))
21733     (stop *(ebp+0x14) 1)
21734     # never gets here
21735 
21736 $check-mu-populate-stmt:error-invalid-target-type:
21737     (write-buffered *(ebp+0x10) "fn ")
21738     8b/-> *(ebp+0xc) 0/r32/eax
21739     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21740     (write-buffered *(ebp+0x10) %eax)
21741     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
21742     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21743     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21744     (write-buffered *(ebp+0x10) %eax)
21745     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
21746     (flush *(ebp+0x10))
21747     (stop *(ebp+0x14) 1)
21748     # never gets here
21749 
21750 $check-mu-populate-stmt:error-invalid-length-type:
21751     (write-buffered *(ebp+0x10) "fn ")
21752     8b/-> *(ebp+0xc) 0/r32/eax
21753     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21754     (write-buffered *(ebp+0x10) %eax)
21755     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
21756     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21757     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21758     (write-buffered *(ebp+0x10) %eax)
21759     (write-buffered *(ebp+0x10) "' must be an int\n")
21760     (flush *(ebp+0x10))
21761     (stop *(ebp+0x14) 1)
21762     # never gets here
21763 
21764 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21765     # . prologue
21766     55/push-ebp
21767     89/<- %ebp 4/r32/esp
21768     # . save registers
21769     50/push-eax
21770     53/push-ebx
21771     56/push-esi
21772     57/push-edi
21773     # esi = stmt
21774     8b/-> *(ebp+8) 6/r32/esi
21775 $check-mu-populate-stream-stmt:check-for-output:
21776     # if stmt->outputs abort
21777     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21778     3d/compare-eax-and 0/imm32
21779     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
21780 $check-mu-populate-stream-stmt:get-target:
21781     # var target/edi: (addr stmt-var) = stmt->inouts
21782     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21783     89/<- %edi 0/r32/eax
21784     # zero inouts
21785     3d/compare-eax-and 0/imm32
21786     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
21787 $check-mu-populate-stream-stmt:get-length:
21788     # var length/esi: (addr stmt-var) = dest->next
21789     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21790     89/<- %esi 0/r32/eax
21791     # 1 inout
21792     3d/compare-eax-and 0/imm32
21793     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
21794     # > 2 inouts
21795     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21796     3d/compare-eax-and 0/imm32
21797     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
21798 $check-mu-populate-stream-stmt:check-target-type:
21799     # var target-type/ebx: (addr type-tree) = target->value->type
21800     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21801     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21802     89/<- %ebx 0/r32/eax
21803 $check-mu-populate-stream-stmt:check-target-type-deref:
21804     # if (target->is-deref?) target-type = target-type->payload
21805     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
21806     3d/compare-eax-and 0/imm32/false
21807     {
21808       74/jump-if-= break/disp8
21809       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21810       # if target-type->right is null, target-type = target-type->left
21811       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21812       {
21813         75/jump-if-!= break/disp8
21814         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21815       }
21816       89/<- %ebx 0/r32/eax
21817     }
21818 $check-mu-populate-stream-stmt:check-target-type-addr:
21819     # if target-type is not addr, abort
21820     (is-mu-addr-type? %ebx)  # => eax
21821     3d/compare-eax-and 0/imm32/false
21822     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
21823     # if target-type->right is an atom, abort
21824     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21825     89/<- %ebx 0/r32/eax
21826     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21827     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
21828 $check-mu-populate-stream-stmt:check-target-type-handle:
21829     # if target-type->right->left is not handle, abort
21830     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21831     (is-simple-mu-type? %eax 4)  # handle => eax
21832     3d/compare-eax-and 0/imm32/false
21833     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
21834     # if target-type->right->right is an atom, abort
21835     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21836     89/<- %ebx 0/r32/eax
21837     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21838     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
21839 $check-mu-populate-stream-stmt:check-target-type-stream:
21840     # if target-type->right->right->left is not stream, abort
21841     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21842     (is-simple-mu-type? %eax 0xb)  # stream => eax
21843     3d/compare-eax-and 0/imm32/false
21844     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
21845 $check-mu-populate-stream-stmt:check-length-type:
21846     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21847     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21848     89/<- %ebx 0/r32/eax
21849     (is-simple-mu-type? %ebx 0)  # literal => eax
21850     3d/compare-eax-and 0/imm32/false
21851     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
21852     (is-simple-mu-type? %ebx 1)  # int => eax
21853     3d/compare-eax-and 0/imm32/false
21854     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
21855 $check-mu-populate-stream-stmt:end:
21856     # . restore registers
21857     5f/pop-to-edi
21858     5e/pop-to-esi
21859     5b/pop-to-ebx
21860     58/pop-to-eax
21861     # . epilogue
21862     89/<- %esp 5/r32/ebp
21863     5d/pop-to-ebp
21864     c3/return
21865 
21866 $check-mu-populate-stream-stmt:error-incorrect-inouts:
21867     (write-buffered *(ebp+0x10) "fn ")
21868     8b/-> *(ebp+0xc) 0/r32/eax
21869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21870     (write-buffered *(ebp+0x10) %eax)
21871     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
21872     (flush *(ebp+0x10))
21873     (stop *(ebp+0x14) 1)
21874     # never gets here
21875 
21876 $check-mu-populate-stream-stmt:error-too-many-outputs:
21877     (write-buffered *(ebp+0x10) "fn ")
21878     8b/-> *(ebp+0xc) 0/r32/eax
21879     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21880     (write-buffered *(ebp+0x10) %eax)
21881     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
21882     (flush *(ebp+0x10))
21883     (stop *(ebp+0x14) 1)
21884     # never gets here
21885 
21886 $check-mu-populate-stream-stmt:error-invalid-target-type:
21887     (write-buffered *(ebp+0x10) "fn ")
21888     8b/-> *(ebp+0xc) 0/r32/eax
21889     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21890     (write-buffered *(ebp+0x10) %eax)
21891     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
21892     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21893     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21894     (write-buffered *(ebp+0x10) %eax)
21895     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
21896     (flush *(ebp+0x10))
21897     (stop *(ebp+0x14) 1)
21898     # never gets here
21899 
21900 $check-mu-populate-stream-stmt:error-invalid-length-type:
21901     (write-buffered *(ebp+0x10) "fn ")
21902     8b/-> *(ebp+0xc) 0/r32/eax
21903     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21904     (write-buffered *(ebp+0x10) %eax)
21905     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
21906     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21907     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21908     (write-buffered *(ebp+0x10) %eax)
21909     (write-buffered *(ebp+0x10) "' must be an int\n")
21910     (flush *(ebp+0x10))
21911     (stop *(ebp+0x14) 1)
21912     # never gets here
21913 
21914 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21915     # . prologue
21916     55/push-ebp
21917     89/<- %ebp 4/r32/esp
21918     # . save registers
21919     50/push-eax
21920     51/push-ecx
21921     52/push-edx
21922     53/push-ebx
21923     56/push-esi
21924     57/push-edi
21925     # esi = stmt
21926     8b/-> *(ebp+8) 6/r32/esi
21927     # - check for 0 inouts
21928     # var base/ecx: (addr var) = stmt->inouts->value
21929     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21930 $check-mu-read-from-stream-stmt:check-no-inouts:
21931     3d/compare-eax-and 0/imm32
21932     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
21933     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21934     89/<- %ecx 0/r32/eax
21935     # - check base type is (addr stream T)
21936     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21937     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21938     89/<- %ebx 0/r32/eax
21939 $check-mu-read-from-stream-stmt:check-base-is-compound:
21940     # if base-type is an atom, abort
21941     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21942     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
21943 $check-mu-read-from-stream-stmt:check-base-is-addr:
21944     # if type->left not addr, abort
21945     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21946     (is-simple-mu-type? %eax 2)  # addr => eax
21947     3d/compare-eax-and 0/imm32/false
21948     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
21949 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
21950     # base-type = base-type->right
21951     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21952     89/<- %ebx 0/r32/eax
21953     # ensure base-type->left == stream
21954     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21955     (is-simple-mu-type? %eax 0xb)  # stream => eax
21956     3d/compare-eax-and 0/imm32/false
21957     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
21958     # - check target type is (addr T)
21959     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
21960     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21961     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21962 $check-mu-read-from-stream-stmt:check-single-inout:
21963     3d/compare-eax-and 0/imm32
21964     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
21965     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21966     89/<- %ecx 0/r32/eax
21967     # var target-type/edx: (addr type-tree)
21968     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21969     89/<- %edx 0/r32/eax
21970     # if target-type is an atom, it must be a literal or int
21971 $check-mu-read-from-stream-stmt:check-target-is-compound:
21972     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21973     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
21974 $check-mu-read-from-stream-stmt:check-target-type:
21975     # target type must start with (addr ...)
21976     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
21977     (is-simple-mu-type? %eax 2)  # addr => eax
21978     3d/compare-eax-and 0/imm32/false
21979     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
21980     # if tail(base-type) != tail(target-type) abort
21981     (type-tail %ebx)  # => eax
21982     89/<- %ebx 0/r32/eax
21983     (type-tail %edx)  # => eax
21984     (type-equal? %ebx %eax)  # => eax
21985     3d/compare-eax-and 0/imm32/false
21986     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
21987 $check-mu-read-from-stream-stmt:check-too-many-inouts:
21988     # - check for too many inouts
21989     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21990     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21991     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21992     3d/compare-eax-and 0/imm32/false
21993     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
21994 $check-mu-read-from-stream-stmt:check-unexpected-output:
21995     # - check for any output
21996     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21997     3d/compare-eax-and 0/imm32/false
21998     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
21999 $check-mu-read-from-stream-stmt:end:
22000     # . restore registers
22001     5f/pop-to-edi
22002     5e/pop-to-esi
22003     5b/pop-to-ebx
22004     5a/pop-to-edx
22005     59/pop-to-ecx
22006     58/pop-to-eax
22007     # . epilogue
22008     89/<- %esp 5/r32/ebp
22009     5d/pop-to-ebp
22010     c3/return
22011 
22012 $check-mu-read-from-stream-stmt:error-invalid-base-type:
22013     (write-buffered *(ebp+0x10) "fn ")
22014     8b/-> *(ebp+0xc) 0/r32/eax
22015     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22016     (write-buffered *(ebp+0x10) %eax)
22017     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
22018     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22019     (write-buffered *(ebp+0x10) %eax)
22020     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
22021     (flush *(ebp+0x10))
22022     (stop *(ebp+0x14) 1)
22023     # never gets here
22024 
22025 $check-mu-read-from-stream-stmt:error-too-few-inouts:
22026     (write-buffered *(ebp+0x10) "fn ")
22027     8b/-> *(ebp+0xc) 0/r32/eax
22028     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22029     (write-buffered *(ebp+0x10) %eax)
22030     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
22031     (flush *(ebp+0x10))
22032     (stop *(ebp+0x14) 1)
22033     # never gets here
22034 
22035 $check-mu-read-from-stream-stmt:error-target-type-not-address:
22036     (write-buffered *(ebp+0x10) "fn ")
22037     8b/-> *(ebp+0xc) 0/r32/eax
22038     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22039     (write-buffered *(ebp+0x10) %eax)
22040     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
22041     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22042     (write-buffered *(ebp+0x10) %eax)
22043     (write-buffered *(ebp+0x10) "' must be an addr\n")
22044     (flush *(ebp+0x10))
22045     (stop *(ebp+0x14) 1)
22046     # never gets here
22047 
22048 $check-mu-read-from-stream-stmt:error-invalid-target-type:
22049     (write-buffered *(ebp+0x10) "fn ")
22050     8b/-> *(ebp+0xc) 0/r32/eax
22051     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22052     (write-buffered *(ebp+0x10) %eax)
22053     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
22054     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22055     (write-buffered *(ebp+0x10) %eax)
22056     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22057     (flush *(ebp+0x10))
22058     (stop *(ebp+0x14) 1)
22059     # never gets here
22060 
22061 $check-mu-read-from-stream-stmt:error-too-many-inouts:
22062     (write-buffered *(ebp+0x10) "fn ")
22063     8b/-> *(ebp+0xc) 0/r32/eax
22064     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22065     (write-buffered *(ebp+0x10) %eax)
22066     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
22067     (flush *(ebp+0x10))
22068     (stop *(ebp+0x14) 1)
22069     # never gets here
22070 
22071 $check-mu-read-from-stream-stmt:error-unexpected-output:
22072     (write-buffered *(ebp+0x10) "fn ")
22073     8b/-> *(ebp+0xc) 0/r32/eax
22074     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22075     (write-buffered *(ebp+0x10) %eax)
22076     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
22077     (flush *(ebp+0x10))
22078     (stop *(ebp+0x14) 1)
22079     # never gets here
22080 
22081 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22082     # . prologue
22083     55/push-ebp
22084     89/<- %ebp 4/r32/esp
22085     # . save registers
22086     50/push-eax
22087     51/push-ecx
22088     52/push-edx
22089     53/push-ebx
22090     56/push-esi
22091     57/push-edi
22092     # esi = stmt
22093     8b/-> *(ebp+8) 6/r32/esi
22094     # - check for 0 inouts
22095     # var base/ecx: (addr var) = stmt->inouts->value
22096     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22097 $check-mu-write-to-stream-stmt:check-no-inouts:
22098     3d/compare-eax-and 0/imm32
22099     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
22100     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22101     89/<- %ecx 0/r32/eax
22102     # - check base type is (addr stream T)
22103     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22104     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22105     89/<- %ebx 0/r32/eax
22106 $check-mu-write-to-stream-stmt:check-base-is-compound:
22107     # if base-type is an atom, abort
22108     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22109     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
22110 $check-mu-write-to-stream-stmt:check-base-is-addr:
22111     # if type->left not addr, abort
22112     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22113     (is-simple-mu-type? %eax 2)  # addr => eax
22114     3d/compare-eax-and 0/imm32/false
22115     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
22116 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
22117     # base-type = base-type->right
22118     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22119     89/<- %ebx 0/r32/eax
22120     # ensure base-type->left == stream
22121     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22122     (is-simple-mu-type? %eax 0xb)  # stream => eax
22123     3d/compare-eax-and 0/imm32/false
22124     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
22125     # - check target type is (addr T)
22126     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
22127     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22128     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22129 $check-mu-write-to-stream-stmt:check-single-inout:
22130     3d/compare-eax-and 0/imm32
22131     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
22132     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22133     89/<- %ecx 0/r32/eax
22134     # var target-type/edx: (addr type-tree)
22135     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22136     89/<- %edx 0/r32/eax
22137     # if target-type is an atom, it must be a literal or int
22138 $check-mu-write-to-stream-stmt:check-target-is-compound:
22139     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22140     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
22141 $check-mu-write-to-stream-stmt:check-target-type:
22142     # target type must start with (addr ...)
22143     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22144     (is-simple-mu-type? %eax 2)  # addr => eax
22145     3d/compare-eax-and 0/imm32/false
22146     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
22147     # if tail(base-type) != tail(target-type) abort
22148     (type-tail %ebx)  # => eax
22149     89/<- %ebx 0/r32/eax
22150     (type-tail %edx)  # => eax
22151     (type-equal? %ebx %eax)  # => eax
22152     3d/compare-eax-and 0/imm32/false
22153     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
22154 $check-mu-write-to-stream-stmt:check-too-many-inouts:
22155     # - check for too many inouts
22156     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22157     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22158     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22159     3d/compare-eax-and 0/imm32/false
22160     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
22161 $check-mu-write-to-stream-stmt:check-unexpected-output:
22162     # - check for any output
22163     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22164     3d/compare-eax-and 0/imm32/false
22165     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
22166 $check-mu-write-to-stream-stmt:end:
22167     # . restore registers
22168     5f/pop-to-edi
22169     5e/pop-to-esi
22170     5b/pop-to-ebx
22171     5a/pop-to-edx
22172     59/pop-to-ecx
22173     58/pop-to-eax
22174     # . epilogue
22175     89/<- %esp 5/r32/ebp
22176     5d/pop-to-ebp
22177     c3/return
22178 
22179 $check-mu-write-to-stream-stmt:error-invalid-base-type:
22180     (write-buffered *(ebp+0x10) "fn ")
22181     8b/-> *(ebp+0xc) 0/r32/eax
22182     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22183     (write-buffered *(ebp+0x10) %eax)
22184     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
22185     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22186     (write-buffered *(ebp+0x10) %eax)
22187     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
22188     (flush *(ebp+0x10))
22189     (stop *(ebp+0x14) 1)
22190     # never gets here
22191 
22192 $check-mu-write-to-stream-stmt:error-too-few-inouts:
22193     (write-buffered *(ebp+0x10) "fn ")
22194     8b/-> *(ebp+0xc) 0/r32/eax
22195     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22196     (write-buffered *(ebp+0x10) %eax)
22197     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
22198     (flush *(ebp+0x10))
22199     (stop *(ebp+0x14) 1)
22200     # never gets here
22201 
22202 $check-mu-write-to-stream-stmt:error-target-type-not-address:
22203     (write-buffered *(ebp+0x10) "fn ")
22204     8b/-> *(ebp+0xc) 0/r32/eax
22205     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22206     (write-buffered *(ebp+0x10) %eax)
22207     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
22208     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22209     (write-buffered *(ebp+0x10) %eax)
22210     (write-buffered *(ebp+0x10) "' must be an addr\n")
22211     (flush *(ebp+0x10))
22212     (stop *(ebp+0x14) 1)
22213     # never gets here
22214 
22215 $check-mu-write-to-stream-stmt:error-invalid-target-type:
22216     (write-buffered *(ebp+0x10) "fn ")
22217     8b/-> *(ebp+0xc) 0/r32/eax
22218     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22219     (write-buffered *(ebp+0x10) %eax)
22220     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
22221     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22222     (write-buffered *(ebp+0x10) %eax)
22223     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22224     (flush *(ebp+0x10))
22225     (stop *(ebp+0x14) 1)
22226     # never gets here
22227 
22228 $check-mu-write-to-stream-stmt:error-too-many-inouts:
22229     (write-buffered *(ebp+0x10) "fn ")
22230     8b/-> *(ebp+0xc) 0/r32/eax
22231     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22232     (write-buffered *(ebp+0x10) %eax)
22233     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
22234     (flush *(ebp+0x10))
22235     (stop *(ebp+0x14) 1)
22236     # never gets here
22237 
22238 $check-mu-write-to-stream-stmt:error-unexpected-output:
22239     (write-buffered *(ebp+0x10) "fn ")
22240     8b/-> *(ebp+0xc) 0/r32/eax
22241     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22242     (write-buffered *(ebp+0x10) %eax)
22243     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
22244     (flush *(ebp+0x10))
22245     (stop *(ebp+0x14) 1)
22246     # never gets here
22247 
22248 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22249     # . prologue
22250     55/push-ebp
22251     89/<- %ebp 4/r32/esp
22252     # . save registers
22253 $check-mu-convert-stmt:end:
22254     # . restore registers
22255     # . epilogue
22256     89/<- %esp 5/r32/ebp
22257     5d/pop-to-ebp
22258     c3/return
22259 
22260 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22261     # . prologue
22262     55/push-ebp
22263     89/<- %ebp 4/r32/esp
22264     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
22265     68/push 0/imm32
22266     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
22267     81 5/subop/subtract %esp 0x60/imm32
22268     68/push 0x60/imm32/size
22269     68/push 0/imm32/read
22270     68/push 0/imm32/write
22271     # save a pointer to type-parameters-storage at type-parameters
22272     89/<- *(ebp-4) 4/r32/esp
22273     (clear-stream *(ebp-4))
22274     # . save registers
22275     50/push-eax
22276     51/push-ecx
22277     52/push-edx
22278     53/push-ebx
22279     56/push-esi
22280     57/push-edi
22281     # esi = stmt
22282     8b/-> *(ebp+8) 6/r32/esi
22283     # edi = callee
22284     8b/-> *(ebp+0xc) 7/r32/edi
22285     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
22286     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22287     89/<- %ecx 0/r32/eax
22288     # var expected/edx: (addr list var) = lookup(f->inouts)
22289     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
22290     89/<- %edx 0/r32/eax
22291     {
22292 $check-mu-call:check-for-inouts:
22293       # if (inouts == 0) break
22294       81 7/subop/compare %ecx 0/imm32
22295       0f 84/jump-if-= break/disp32
22296       # if (expected == 0) error
22297       81 7/subop/compare %edx 0/imm32
22298       0f 84/jump-if-= break/disp32
22299 $check-mu-call:check-inout-type:
22300       # var v/eax: (addr v) = lookup(inouts->value)
22301       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22302       # var t/ebx: (addr type-tree) = lookup(v->type)
22303       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22304       89/<- %ebx 0/r32/eax
22305       # if (inouts->is-deref?) t = t->right  # TODO: check that t->left is an addr
22306       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
22307       {
22308         74/jump-if-= break/disp8
22309         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22310         89/<- %ebx 0/r32/eax
22311         # if t->right is null, t = t->left
22312         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
22313         75/jump-if-!= break/disp8
22314         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22315         89/<- %ebx 0/r32/eax
22316       }
22317       # var v2/eax: (addr v) = lookup(expected->value)
22318       (lookup *edx *(edx+4))  # List-value List-value => eax
22319       # var t2/eax: (addr type-tree) = lookup(v2->type)
22320       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22321       # if (t != t2) error
22322       (type-match? %eax %ebx *(ebp-4))  # => eax
22323       3d/compare-eax-and 0/imm32/false
22324       {
22325         0f 85/jump-if-!= break/disp32
22326         (write-buffered *(ebp+0x14) "fn ")
22327         8b/-> *(ebp+0x10) 0/r32/eax
22328         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22329         (write-buffered *(ebp+0x14) %eax)
22330         (write-buffered *(ebp+0x14) ": call ")
22331         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22332         (write-buffered *(ebp+0x14) %eax)
22333         (write-buffered *(ebp+0x14) ": type for inout '")
22334         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22335         (lookup *eax *(eax+4))  # Var-name Var-name => eax
22336         (write-buffered *(ebp+0x14) %eax)
22337         (write-buffered *(ebp+0x14) "' is not right\n")
22338         (flush *(ebp+0x14))
22339         (stop *(ebp+0x18) 1)
22340       }
22341 $check-mu-call:continue-to-next-inout:
22342       # inouts = lookup(inouts->next)
22343       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
22344       89/<- %ecx 0/r32/eax
22345       # expected = lookup(expected->next)
22346       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
22347       89/<- %edx 0/r32/eax
22348       #
22349       e9/jump loop/disp32
22350     }
22351 $check-mu-call:check-inout-count:
22352     # if (inouts == expected) proceed
22353     39/compare %ecx 2/r32/edx
22354     {
22355       0f 84/jump-if-= break/disp32
22356       # exactly one of the two is null
22357       # if (inouts == 0) error("too many inouts")
22358       {
22359         81 7/subop/compare %ecx 0/imm32
22360         0f 84/jump-if-= break/disp32
22361         (write-buffered *(ebp+0x14) "fn ")
22362         8b/-> *(ebp+0x10) 0/r32/eax
22363         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22364         (write-buffered *(ebp+0x14) %eax)
22365         (write-buffered *(ebp+0x14) ": call ")
22366         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22367         (write-buffered *(ebp+0x14) %eax)
22368         (write-buffered *(ebp+0x14) ": too many inouts\n")
22369         (flush *(ebp+0x14))
22370         (stop *(ebp+0x18) 1)
22371       }
22372       # if (expected == 0) error("too few inouts")
22373       {
22374         81 7/subop/compare %edx 0/imm32
22375         0f 84/jump-if-= break/disp32
22376         (write-buffered *(ebp+0x14) "fn ")
22377         8b/-> *(ebp+0x10) 0/r32/eax
22378         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22379         (write-buffered *(ebp+0x14) %eax)
22380         (write-buffered *(ebp+0x14) ": call ")
22381         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22382         (write-buffered *(ebp+0x14) %eax)
22383         (write-buffered *(ebp+0x14) ": too few inouts\n")
22384         (flush *(ebp+0x14))
22385         (stop *(ebp+0x18) 1)
22386       }
22387     }
22388 $check-mu-call:check-outputs:
22389     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
22390     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22391     89/<- %ecx 0/r32/eax
22392     # var expected/edx: (addr list var) = lookup(f->outputs)
22393     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
22394     89/<- %edx 0/r32/eax
22395     {
22396 $check-mu-call:check-for-outputs:
22397       # if (outputs == 0) break
22398       81 7/subop/compare %ecx 0/imm32
22399       0f 84/jump-if-= break/disp32
22400       # if (expected == 0) error
22401       81 7/subop/compare %edx 0/imm32
22402       0f 84/jump-if-= break/disp32
22403 $check-mu-call:check-output-type:
22404       # var v/eax: (addr v) = lookup(outputs->value)
22405       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22406       # var t/ebx: (addr type-tree) = lookup(v->type)
22407       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22408       89/<- %ebx 0/r32/eax
22409       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
22410       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
22411       {
22412         74/jump-if-= break/disp8
22413         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22414         89/<- %ebx 0/r32/eax
22415       }
22416       # var v2/eax: (addr v) = lookup(expected->value)
22417       (lookup *edx *(edx+4))  # List-value List-value => eax
22418       # var t2/eax: (addr type-tree) = lookup(v2->type)
22419       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22420       # if (t != t2) error
22421       (type-match? %eax %ebx *(ebp-4))  # => eax
22422       3d/compare-eax-and 0/imm32/false
22423       {
22424         0f 85/jump-if-!= break/disp32
22425         (write-buffered *(ebp+0x14) "fn ")
22426         8b/-> *(ebp+0x10) 0/r32/eax
22427         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22428         (write-buffered *(ebp+0x14) %eax)
22429         (write-buffered *(ebp+0x14) ": call ")
22430         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22431         (write-buffered *(ebp+0x14) %eax)
22432         (write-buffered *(ebp+0x14) ": type for output '")
22433         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22434         (lookup *eax *(eax+4))  # Var-name Var-name => eax
22435         (write-buffered *(ebp+0x14) %eax)
22436         (write-buffered *(ebp+0x14) "' is not right\n")
22437         (flush *(ebp+0x14))
22438         (stop *(ebp+0x18) 1)
22439       }
22440 $check-mu-call:check-output-register:
22441       # var v/eax: (addr v) = lookup(outputs->value)
22442       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22443       # var r/ebx: (addr array byte) = lookup(v->register)
22444       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
22445       89/<- %ebx 0/r32/eax
22446       # if (r == 0) error
22447       3d/compare-eax-and 0/imm32
22448       {
22449         0f 85/jump-if-!= break/disp32
22450         (write-buffered *(ebp+0x14) "fn ")
22451         8b/-> *(ebp+0x10) 0/r32/eax
22452         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22453         (write-buffered *(ebp+0x14) %eax)
22454         (write-buffered *(ebp+0x14) ": call ")
22455         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22456         (write-buffered *(ebp+0x14) %eax)
22457         (write-buffered *(ebp+0x14) ": output '")
22458         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22459         (lookup *eax *(eax+4))  # Var-name Var-name => eax
22460         (write-buffered *(ebp+0x14) %eax)
22461         (write-buffered *(ebp+0x14) "' is not in a register\n")
22462         (flush *(ebp+0x14))
22463         (stop *(ebp+0x18) 1)
22464       }
22465       # var v2/eax: (addr v) = lookup(expected->value)
22466       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
22467       # var r2/eax: (addr array byte) = lookup(v2->register)
22468       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
22469       # if (r != r2) error
22470       (string-equal? %eax %ebx)  # => eax
22471       3d/compare-eax-and 0/imm32/false
22472       {
22473         0f 85/jump-if-!= break/disp32
22474         (write-buffered *(ebp+0x14) "fn ")
22475         8b/-> *(ebp+0x10) 0/r32/eax
22476         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22477         (write-buffered *(ebp+0x14) %eax)
22478         (write-buffered *(ebp+0x14) ": call ")
22479         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22480         (write-buffered *(ebp+0x14) %eax)
22481         (write-buffered *(ebp+0x14) ": register for output '")
22482         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22483         (lookup *eax *(eax+4))  # Var-name Var-name => eax
22484         (write-buffered *(ebp+0x14) %eax)
22485         (write-buffered *(ebp+0x14) "' is not right\n")
22486         (flush *(ebp+0x14))
22487         (stop *(ebp+0x18) 1)
22488       }
22489 $check-mu-call:continue-to-next-output:
22490       # outputs = lookup(outputs->next)
22491       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
22492       89/<- %ecx 0/r32/eax
22493       # expected = lookup(expected->next)
22494       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
22495       89/<- %edx 0/r32/eax
22496       #
22497       e9/jump loop/disp32
22498     }
22499 $check-mu-call:check-output-count:
22500     # if (outputs == expected) proceed
22501     39/compare %ecx 2/r32/edx
22502     {
22503       0f 84/jump-if-= break/disp32
22504       # exactly one of the two is null
22505       # if (outputs == 0) error("too many outputs")
22506       {
22507         81 7/subop/compare %ecx 0/imm32
22508         0f 84/jump-if-= break/disp32
22509         (write-buffered *(ebp+0x14) "fn ")
22510         8b/-> *(ebp+0x10) 0/r32/eax
22511         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22512         (write-buffered *(ebp+0x14) %eax)
22513         (write-buffered *(ebp+0x14) ": call ")
22514         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22515         (write-buffered *(ebp+0x14) %eax)
22516         (write-buffered *(ebp+0x14) ": too many outputs\n")
22517         (flush *(ebp+0x14))
22518         (stop *(ebp+0x18) 1)
22519       }
22520       # if (expected == 0) error("too few outputs")
22521       {
22522         81 7/subop/compare %edx 0/imm32
22523         0f 84/jump-if-= break/disp32
22524         (write-buffered *(ebp+0x14) "fn ")
22525         8b/-> *(ebp+0x10) 0/r32/eax
22526         (lookup *eax *(eax+4))  # Function-name Function-name => eax
22527         (write-buffered *(ebp+0x14) %eax)
22528         (write-buffered *(ebp+0x14) ": call ")
22529         (lookup *edi *(edi+4))  # Function-name Function-name => eax
22530         (write-buffered *(ebp+0x14) %eax)
22531         (write-buffered *(ebp+0x14) ": too few outputs\n")
22532         (flush *(ebp+0x14))
22533         (stop *(ebp+0x18) 1)
22534       }
22535     }
22536 $check-mu-call:end:
22537     # . restore registers
22538     5f/pop-to-edi
22539     5e/pop-to-esi
22540     5b/pop-to-ebx
22541     5a/pop-to-edx
22542     59/pop-to-ecx
22543     58/pop-to-eax
22544     # . reclaim locals exclusively on the stack
22545     81 0/subop/add %esp 0x70/imm32
22546     # . epilogue
22547     89/<- %esp 5/r32/ebp
22548     5d/pop-to-ebp
22549     c3/return
22550 
22551 # like type-equal? but takes literals into account
22552 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
22553     # . prologue
22554     55/push-ebp
22555     89/<- %ebp 4/r32/esp
22556     # if (call == literal) return true  # TODO: more precise
22557     (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
22558     3d/compare-eax-and 0/imm32/false
22559     b8/copy-to-eax 1/imm32/true
22560     75/jump-if-!= $type-match?:end/disp8
22561 $type-match?:baseline:
22562     # otherwise fall back
22563     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
22564 $type-match?:end:
22565     # . epilogue
22566     89/<- %esp 5/r32/ebp
22567     5d/pop-to-ebp
22568     c3/return
22569 
22570 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
22571     # . prologue
22572     55/push-ebp
22573     89/<- %ebp 4/r32/esp
22574     # . save registers
22575     51/push-ecx
22576     52/push-edx
22577     53/push-ebx
22578     # ecx = def
22579     8b/-> *(ebp+8) 1/r32/ecx
22580     # edx = call
22581     8b/-> *(ebp+0xc) 2/r32/edx
22582 $type-component-match?:compare-addr:
22583     # if (def == call) return true
22584     8b/-> %ecx 0/r32/eax  # Var-type
22585     39/compare %edx 0/r32/eax  # Var-type
22586     b8/copy-to-eax 1/imm32/true
22587     0f 84/jump-if-= $type-component-match?:end/disp32
22588     # if (def == 0) return false
22589     b8/copy-to-eax 0/imm32/false
22590     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
22591     0f 84/jump-if-= $type-component-match?:end/disp32
22592     # if (call == 0) return false
22593     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
22594     0f 84/jump-if-= $type-component-match?:end/disp32
22595     # if def is a type parameter, just check in type-parameters
22596     {
22597 $type-component-match?:check-type-parameter:
22598       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22599       74/jump-if-= break/disp8
22600       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
22601       75/jump-if-!= break/disp8
22602 $type-component-match?:type-parameter:
22603       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
22604       e9/jump $type-component-match?:end/disp32
22605     }
22606     # if def is a list containing just a type parameter, just check in type-parameters
22607     {
22608 $type-component-match?:check-list-type-parameter:
22609       # if def is a list..
22610       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22611       75/jump-if-!= break/disp8
22612       #   ..that's a singleton
22613       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
22614       75/jump-if-!= break/disp8
22615       #   ..and whose head is a type parameter
22616       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22617       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22618       74/jump-if-= break/disp8
22619       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
22620       75/jump-if-!= break/disp8
22621 $type-component-match?:list-type-parameter:
22622       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
22623       e9/jump $type-component-match?:end/disp32
22624     }
22625 $type-component-match?:compare-atom-state:
22626     # if (def->is-atom? != call->is-atom?) return false
22627     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
22628     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
22629     b8/copy-to-eax 0/imm32/false
22630     0f 85/jump-if-!= $type-component-match?:end/disp32
22631     # if def->is-atom? return (def->value == call->value)
22632     {
22633 $type-component-match?:check-atom:
22634       81 7/subop/compare %ebx 0/imm32/false
22635       74/jump-if-= break/disp8
22636 $type-component-match?:is-atom:
22637       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
22638       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
22639       0f 94/set-if-= %al
22640       81 4/subop/and %eax 0xff/imm32
22641       e9/jump $type-component-match?:end/disp32
22642     }
22643 $type-component-match?:check-left:
22644     # if (!type-component-match?(def->left, call->left)) return false
22645     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22646     89/<- %ebx 0/r32/eax
22647     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22648     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
22649     3d/compare-eax-and 0/imm32/false
22650     74/jump-if-= $type-component-match?:end/disp8
22651 $type-component-match?:check-right:
22652     # return type-component-match?(def->right, call->right)
22653     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22654     89/<- %ebx 0/r32/eax
22655     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
22656     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
22657 $type-component-match?:end:
22658     # . restore registers
22659     5b/pop-to-ebx
22660     5a/pop-to-edx
22661     59/pop-to-ecx
22662     # . epilogue
22663     89/<- %esp 5/r32/ebp
22664     5d/pop-to-ebp
22665     c3/return
22666 
22667 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
22668     # . prologue
22669     55/push-ebp
22670     89/<- %ebp 4/r32/esp
22671     # . save registers
22672     51/push-ecx
22673     #
22674     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
22675     # if parameter wasn't saved, save it
22676     {
22677       81 7/subop/compare *eax 0/imm32
22678       75/jump-if-!= break/disp8
22679       8b/-> *(ebp+0x10) 1/r32/ecx
22680       89/<- *eax 1/r32/ecx
22681     }
22682     #
22683     (type-equal? *(ebp+0x10) *eax)  # => eax
22684 $type-parameter-match?:end:
22685     # . restore registers
22686     59/pop-to-ecx
22687     # . epilogue
22688     89/<- %esp 5/r32/ebp
22689     5d/pop-to-ebp
22690     c3/return
22691 
22692 size-of:  # v: (addr var) -> result/eax: int
22693     # . prologue
22694     55/push-ebp
22695     89/<- %ebp 4/r32/esp
22696     # . save registers
22697     51/push-ecx
22698     # var t/ecx: (addr type-tree) = lookup(v->type)
22699     8b/-> *(ebp+8) 1/r32/ecx
22700 #?     (write-buffered Stderr "size-of ")
22701 #?     (write-int32-hex-buffered Stderr %ecx)
22702 #?     (write-buffered Stderr Newline)
22703 #?     (write-buffered Stderr "type allocid: ")
22704 #?     (write-int32-hex-buffered Stderr *(ecx+8))
22705 #?     (write-buffered Stderr Newline)
22706 #?     (flush Stderr)
22707     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22708     89/<- %ecx 0/r32/eax
22709     # if is-mu-array?(t) return size-of-array(t)
22710     {
22711       (is-mu-array? %ecx)  # => eax
22712       3d/compare-eax-and 0/imm32/false
22713       74/jump-if-= break/disp8
22714       (size-of-array %ecx)  # => eax
22715       eb/jump $size-of:end/disp8
22716     }
22717     # if is-mu-stream?(t) return size-of-stream(t)
22718     {
22719       (is-mu-stream? %ecx)  # => eax
22720       3d/compare-eax-and 0/imm32/false
22721       74/jump-if-= break/disp8
22722       (size-of-stream %ecx)  # => eax
22723       eb/jump $size-of:end/disp8
22724     }
22725     # if (!t->is-atom?) t = lookup(t->left)
22726     {
22727       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22728       75/jump-if-!= break/disp8
22729       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22730       89/<- %ecx 0/r32/eax
22731     }
22732     # TODO: assert t->is-atom?
22733     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
22734 $size-of:end:
22735     # . restore registers
22736     59/pop-to-ecx
22737     # . epilogue
22738     89/<- %esp 5/r32/ebp
22739     5d/pop-to-ebp
22740     c3/return
22741 
22742 size-of-deref:  # v: (addr var) -> result/eax: int
22743     # . prologue
22744     55/push-ebp
22745     89/<- %ebp 4/r32/esp
22746     # . save registers
22747     51/push-ecx
22748     # var t/ecx: (addr type-tree) = lookup(v->type)
22749     8b/-> *(ebp+8) 1/r32/ecx
22750     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22751     89/<- %ecx 0/r32/eax
22752     # TODO: assert(t is an addr)
22753     # t = lookup(t->right)
22754     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22755     89/<- %ecx 0/r32/eax
22756     # if is-mu-array?(t) return size-of-array(t)
22757     {
22758       (is-mu-array? %ecx)  # => eax
22759       3d/compare-eax-and 0/imm32/false
22760       74/jump-if-= break/disp8
22761       (size-of-array %ecx)  # => eax
22762       eb/jump $size-of-deref:end/disp8
22763     }
22764     # if is-mu-stream?(t) return size-of-stream(t)
22765     {
22766       (is-mu-stream? %ecx)  # => eax
22767       3d/compare-eax-and 0/imm32/false
22768       74/jump-if-= break/disp8
22769       (size-of-stream %ecx)  # => eax
22770       eb/jump $size-of-deref:end/disp8
22771     }
22772     # if (!t->is-atom?) t = lookup(t->left)
22773     {
22774       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22775       75/jump-if-!= break/disp8
22776       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22777       89/<- %ecx 0/r32/eax
22778     }
22779     # TODO: assert t->is-atom?
22780     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
22781 $size-of-deref:end:
22782     # . restore registers
22783     59/pop-to-ecx
22784     # . epilogue
22785     89/<- %esp 5/r32/ebp
22786     5d/pop-to-ebp
22787     c3/return
22788 
22789 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
22790     # . prologue
22791     55/push-ebp
22792     89/<- %ebp 4/r32/esp
22793     # . save registers
22794     51/push-ecx
22795     # ecx = t
22796     8b/-> *(ebp+8) 1/r32/ecx
22797     # if t->is-atom?, return false
22798     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22799     75/jump-if-!= $is-mu-array?:return-false/disp8
22800     # if !t->left->is-atom?, return false
22801     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22802     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22803     74/jump-if-= $is-mu-array?:return-false/disp8
22804     # return t->left->value == array
22805     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
22806     0f 94/set-if-= %al
22807     81 4/subop/and %eax 0xff/imm32
22808     eb/jump $is-mu-array?:end/disp8
22809 $is-mu-array?:return-false:
22810     b8/copy-to-eax 0/imm32/false
22811 $is-mu-array?:end:
22812     # . restore registers
22813     59/pop-to-ecx
22814     # . epilogue
22815     89/<- %esp 5/r32/ebp
22816     5d/pop-to-ebp
22817     c3/return
22818 
22819 # size of a statically allocated array where the size is part of the type expression
22820 size-of-array:  # a: (addr type-tree) -> result/eax: int
22821     # . prologue
22822     55/push-ebp
22823     89/<- %ebp 4/r32/esp
22824     # . save registers
22825     51/push-ecx
22826     52/push-edx
22827     #
22828     8b/-> *(ebp+8) 1/r32/ecx
22829     # TODO: assert that a->left is 'array'
22830     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22831     89/<- %ecx 0/r32/eax
22832     # var elem-type/edx: type-id = a->right->left->value
22833     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22834     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
22835     # TODO: assert that a->right->right->left->value == size
22836     # var array-size/ecx: int = a->right->right->left->value-size
22837     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22838     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22839     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
22840     # return 4 + array-size * size-of(elem-type)
22841     (size-of-type-id-as-array-element %edx)  # => eax
22842     f7 4/subop/multiply-into-edx-eax %ecx
22843     05/add-to-eax 4/imm32  # for array size
22844     # TODO: check edx for overflow
22845 $size-of-array:end:
22846     # . restore registers
22847     5a/pop-to-edx
22848     59/pop-to-ecx
22849     # . epilogue
22850     89/<- %esp 5/r32/ebp
22851     5d/pop-to-ebp
22852     c3/return
22853 
22854 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
22855     # . prologue
22856     55/push-ebp
22857     89/<- %ebp 4/r32/esp
22858     # . save registers
22859     51/push-ecx
22860     # ecx = t
22861     8b/-> *(ebp+8) 1/r32/ecx
22862     # if t->is-atom?, return false
22863     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22864     75/jump-if-!= $is-mu-stream?:return-false/disp8
22865     # if !t->left->is-atom?, return false
22866     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22867     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22868     74/jump-if-= $is-mu-stream?:return-false/disp8
22869     # return t->left->value == stream
22870     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
22871     0f 94/set-if-= %al
22872     81 4/subop/and %eax 0xff/imm32
22873     eb/jump $is-mu-stream?:end/disp8
22874 $is-mu-stream?:return-false:
22875     b8/copy-to-eax 0/imm32/false
22876 $is-mu-stream?:end:
22877     # . restore registers
22878     59/pop-to-ecx
22879     # . epilogue
22880     89/<- %esp 5/r32/ebp
22881     5d/pop-to-ebp
22882     c3/return
22883 
22884 # size of a statically allocated stream where the size is part of the type expression
22885 size-of-stream:  # a: (addr type-tree) -> result/eax: int
22886     # . prologue
22887     55/push-ebp
22888     89/<- %ebp 4/r32/esp
22889     #
22890     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
22891     05/add-to-eax 8/imm32  # for read/write pointers
22892 $size-of-stream:end:
22893     # . epilogue
22894     89/<- %esp 5/r32/ebp
22895     5d/pop-to-ebp
22896     c3/return
22897 
22898 size-of-type-id:  # t: type-id -> result/eax: int
22899     # . prologue
22900     55/push-ebp
22901     89/<- %ebp 4/r32/esp
22902     # . save registers
22903     51/push-ecx
22904     # var out/ecx: (handle typeinfo)
22905     68/push 0/imm32
22906     68/push 0/imm32
22907     89/<- %ecx 4/r32/esp
22908     # eax = t
22909     8b/-> *(ebp+8) 0/r32/eax
22910     # if t is a literal, return 0
22911     3d/compare-eax-and 0/imm32
22912     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
22913     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
22914     3d/compare-eax-and 8/imm32/byte
22915     {
22916       75/jump-if-!= break/disp8
22917       b8/copy-to-eax 4/imm32
22918       eb/jump $size-of-type-id:end/disp8
22919     }
22920     # if t is a handle, return 8
22921     3d/compare-eax-and 4/imm32/handle
22922     {
22923       75/jump-if-!= break/disp8
22924       b8/copy-to-eax 8/imm32
22925       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
22926     }
22927     # if t is a slice, return 8
22928     3d/compare-eax-and 0xc/imm32/slice
22929     {
22930       75/jump-if-!= break/disp8
22931       b8/copy-to-eax 8/imm32
22932       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
22933     }
22934     # if t is a user-defined type, return its size
22935     # TODO: support non-atom type
22936     (find-typeinfo %eax %ecx)
22937     {
22938       81 7/subop/compare *ecx 0/imm32
22939       74/jump-if-= break/disp8
22940 $size-of-type-id:user-defined:
22941       (lookup *ecx *(ecx+4))  # => eax
22942       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
22943       eb/jump $size-of-type-id:end/disp8
22944     }
22945     # otherwise return the word size
22946     b8/copy-to-eax 4/imm32
22947 $size-of-type-id:end:
22948     # . reclaim locals
22949     81 0/subop/add %esp 8/imm32
22950     # . restore registers
22951     59/pop-to-ecx
22952     # . epilogue
22953     89/<- %esp 5/r32/ebp
22954     5d/pop-to-ebp
22955     c3/return
22956 
22957 # Minor violation of our type system since it returns an addr. But we could
22958 # replace it with a handle some time.
22959 # Returns null if t is an atom.
22960 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
22961     # . prologue
22962     55/push-ebp
22963     89/<- %ebp 4/r32/esp
22964     # . save registers
22965     51/push-ecx
22966     # eax = 0
22967     b8/copy-to-eax 0/imm32
22968     # ecx = t
22969     8b/-> *(ebp+8) 1/r32/ecx
22970 $type-tail:check-atom:
22971     # if t->is-atom? return 0
22972     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22973     0f 85/jump-if-!= $type-tail:end/disp32
22974     # var tail = t->right
22975     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22976     89/<- %ecx 0/r32/eax
22977 $type-tail:check-singleton:
22978     # if (tail->right == 0) return tail->left
22979     {
22980       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
22981       75/jump-if-!= break/disp8
22982       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22983       e9/jump $type-tail:end/disp32
22984     }
22985     # if tail->right->left is an array-capacity, return tail->left
22986     {
22987 $type-tail:check-array-capacity:
22988       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22989       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22990       75/jump-if-!= break/disp8
22991 $type-tail:check-array-capacity-1:
22992       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22993       3d/compare-eax-and 0/imm32
22994       74/jump-if-= break/disp8
22995 $type-tail:check-array-capacity-2:
22996       (is-simple-mu-type? %eax 9)  # array-capacity => eax
22997       3d/compare-eax-and 0/imm32/false
22998       74/jump-if-= break/disp8
22999 $type-tail:array-capacity:
23000       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23001       eb/jump $type-tail:end/disp8
23002     }
23003 $type-tail:check-compound-left:
23004     # if !tail->left->is-atom? return tail->left
23005     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23006     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23007     74/jump-if-= $type-tail:end/disp8
23008 $type-tail:return-tail:
23009     # return tail
23010     89/<- %eax 1/r32/ecx
23011 $type-tail:end:
23012     # . restore registers
23013     59/pop-to-ecx
23014     # . epilogue
23015     89/<- %esp 5/r32/ebp
23016     5d/pop-to-ebp
23017     c3/return
23018 
23019 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23020     # . prologue
23021     55/push-ebp
23022     89/<- %ebp 4/r32/esp
23023     # . save registers
23024     51/push-ecx
23025     52/push-edx
23026     53/push-ebx
23027     # ecx = a
23028     8b/-> *(ebp+8) 1/r32/ecx
23029     # edx = b
23030     8b/-> *(ebp+0xc) 2/r32/edx
23031 $type-equal?:compare-addr:
23032     # if (a == b) return true
23033     8b/-> %ecx 0/r32/eax  # Var-type
23034     39/compare %edx 0/r32/eax  # Var-type
23035     b8/copy-to-eax 1/imm32/true
23036     0f 84/jump-if-= $type-equal?:end/disp32
23037 $type-equal?:compare-null-a:
23038     # if (a == 0) return false
23039     b8/copy-to-eax 0/imm32/false
23040     81 7/subop/compare %ecx 0/imm32
23041     0f 84/jump-if-= $type-equal?:end/disp32
23042 $type-equal?:compare-null-b:
23043     # if (b == 0) return false
23044     81 7/subop/compare %edx 0/imm32
23045     0f 84/jump-if-= $type-equal?:end/disp32
23046 $type-equal?:compare-atom-state:
23047     # if (a->is-atom? != b->is-atom?) return false
23048     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
23049     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
23050     b8/copy-to-eax 0/imm32/false
23051     0f 85/jump-if-!= $type-equal?:end/disp32
23052     # if a->is-atom? return (a->value == b->value)
23053     {
23054 $type-equal?:check-atom:
23055       81 7/subop/compare %ebx 0/imm32/false
23056       74/jump-if-= break/disp8
23057 $type-equal?:is-atom:
23058       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
23059       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
23060       0f 94/set-if-= %al
23061       81 4/subop/and %eax 0xff/imm32
23062       e9/jump $type-equal?:end/disp32
23063     }
23064 $type-equal?:check-left:
23065     # if (!type-equal?(a->left, b->left)) return false
23066     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23067     89/<- %ebx 0/r32/eax
23068     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23069     (type-equal? %eax %ebx)  # => eax
23070     3d/compare-eax-and 0/imm32/false
23071     74/jump-if-= $type-equal?:end/disp8
23072 $type-equal?:check-right:
23073     # return type-equal?(a->right, b->right)
23074     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23075     89/<- %ebx 0/r32/eax
23076     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
23077     (type-equal? %eax %ebx)  # => eax
23078 $type-equal?:end:
23079     # . restore registers
23080     5b/pop-to-ebx
23081     5a/pop-to-edx
23082     59/pop-to-ecx
23083     # . epilogue
23084     89/<- %esp 5/r32/ebp
23085     5d/pop-to-ebp
23086     c3/return
23087 
23088 #######################################################
23089 # Code-generation
23090 #######################################################
23091 
23092 == data
23093 
23094 # Global state added to each var record when performing code-generation.
23095 Curr-local-stack-offset:  # (addr int)
23096     0/imm32
23097 
23098 == code
23099 
23100 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
23101     # . prologue
23102     55/push-ebp
23103     89/<- %ebp 4/r32/esp
23104     # . save registers
23105     50/push-eax
23106     # var curr/eax: (addr function) = *Program->functions
23107     (lookup *_Program-functions *_Program-functions->payload)  # => eax
23108     {
23109       # if (curr == null) break
23110       3d/compare-eax-and 0/imm32
23111       0f 84/jump-if-= break/disp32
23112       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
23113       # curr = lookup(curr->next)
23114       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
23115       e9/jump loop/disp32
23116     }
23117 $emit-subx:end:
23118     # . restore registers
23119     58/pop-to-eax
23120     # . epilogue
23121     89/<- %esp 5/r32/ebp
23122     5d/pop-to-ebp
23123     c3/return
23124 
23125 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23126     # . prologue
23127     55/push-ebp
23128     89/<- %ebp 4/r32/esp
23129     # some preprocessing
23130     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
23131     # . save registers
23132     50/push-eax
23133     51/push-ecx
23134     52/push-edx
23135     # initialize some global state
23136     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
23137     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
23138     # ecx = f
23139     8b/-> *(ebp+0xc) 1/r32/ecx
23140     # var vars/edx: (stack (addr var) 256)
23141     81 5/subop/subtract %esp 0xc00/imm32
23142     68/push 0xc00/imm32/size
23143     68/push 0/imm32/top
23144     89/<- %edx 4/r32/esp
23145     # var name/eax: (addr array byte) = lookup(f->name)
23146     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
23147     #
23148     (write-buffered *(ebp+8) %eax)
23149     (write-buffered *(ebp+8) ":\n")
23150     (emit-subx-prologue *(ebp+8))
23151     # var body/eax: (addr block) = lookup(f->body)
23152     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
23153     #
23154     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
23155     (emit-subx-epilogue *(ebp+8))
23156     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
23157     # been cleaned up
23158 $emit-subx-function:end:
23159     # . reclaim locals
23160     81 0/subop/add %esp 0xc08/imm32
23161     # . restore registers
23162     5a/pop-to-edx
23163     59/pop-to-ecx
23164     58/pop-to-eax
23165     # . epilogue
23166     89/<- %esp 5/r32/ebp
23167     5d/pop-to-ebp
23168     c3/return
23169 
23170 populate-mu-type-offsets-in-inouts:  # f: (addr function)
23171     # . prologue
23172     55/push-ebp
23173     89/<- %ebp 4/r32/esp
23174     # . save registers
23175     50/push-eax
23176     51/push-ecx
23177     52/push-edx
23178     53/push-ebx
23179     57/push-edi
23180     # var next-offset/edx: int = 8
23181     ba/copy-to-edx 8/imm32
23182     # var curr/ecx: (addr list var) = lookup(f->inouts)
23183     8b/-> *(ebp+8) 1/r32/ecx
23184     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
23185     89/<- %ecx 0/r32/eax
23186     {
23187 $populate-mu-type-offsets-in-inouts:loop:
23188       81 7/subop/compare %ecx 0/imm32
23189       74/jump-if-= break/disp8
23190       # var v/ebx: (addr var) = lookup(curr->value)
23191       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23192       89/<- %ebx 0/r32/eax
23193 #?       (lookup *ebx *(ebx+4))
23194 #?       (write-buffered Stderr "setting offset of fn inout ")
23195 #?       (write-buffered Stderr %eax)
23196 #?       (write-buffered Stderr "@")
23197 #?       (write-int32-hex-buffered Stderr %ebx)
23198 #?       (write-buffered Stderr " to ")
23199 #?       (write-int32-hex-buffered Stderr %edx)
23200 #?       (write-buffered Stderr Newline)
23201 #?       (flush Stderr)
23202       # v->offset = next-offset
23203       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
23204       # next-offset += size-of(v)
23205       (size-of %ebx)  # => eax
23206       01/add-to %edx 0/r32/eax
23207       # curr = lookup(curr->next)
23208       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23209       89/<- %ecx 0/r32/eax
23210       #
23211       eb/jump loop/disp8
23212     }
23213 $populate-mu-type-offsets-in-inouts:end:
23214     # . restore registers
23215     5f/pop-to-edi
23216     5b/pop-to-ebx
23217     5a/pop-to-edx
23218     59/pop-to-ecx
23219     58/pop-to-eax
23220     # . epilogue
23221     89/<- %esp 5/r32/ebp
23222     5d/pop-to-ebp
23223     c3/return
23224 
23225 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)
23226     # . prologue
23227     55/push-ebp
23228     89/<- %ebp 4/r32/esp
23229     # . save registers
23230     50/push-eax
23231     51/push-ecx
23232     53/push-ebx
23233     56/push-esi
23234     # esi = stmts
23235     8b/-> *(ebp+0xc) 6/r32/esi
23236     #
23237     {
23238 $emit-subx-stmt-list:loop:
23239       81 7/subop/compare %esi 0/imm32
23240       0f 84/jump-if-= break/disp32
23241       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
23242       (lookup *esi *(esi+4))  # List-value List-value => eax
23243       89/<- %ecx 0/r32/eax
23244       {
23245 $emit-subx-stmt-list:check-for-block:
23246         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
23247         75/jump-if-!= break/disp8
23248 $emit-subx-stmt-list:block:
23249         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
23250       }
23251       {
23252 $emit-subx-stmt-list:check-for-stmt:
23253         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
23254         0f 85/jump-if-!= break/disp32
23255 $emit-subx-stmt-list:stmt1:
23256         {
23257           (is-mu-branch? %ecx)  # => eax
23258           3d/compare-eax-and 0/imm32/false
23259           0f 84/jump-if-= break/disp32
23260 $emit-subx-stmt-list:branch-stmt:
23261 +-- 25 lines: # unconditional return -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
23286 +-- 27 lines: # unconditional loops ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
23313 +-- 16 lines: # unconditional breaks -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
23329 +-- 38 lines: # simple conditional branches without a target -----------------------------------------------------------------------------------------------------------------------------------------------------
23367 +-- 19 lines: # conditional branches with an explicit target -----------------------------------------------------------------------------------------------------------------------------------------------------
23386         }
23387 $emit-subx-stmt-list:1-to-1:
23388         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
23389         e9/jump $emit-subx-stmt-list:continue/disp32
23390       }
23391       {
23392 $emit-subx-stmt-list:check-for-var-def:
23393         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
23394         75/jump-if-!= break/disp8
23395 $emit-subx-stmt-list:var-def:
23396         (emit-subx-var-def *(ebp+8) %ecx)
23397         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
23398         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
23399         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
23400         #
23401         eb/jump $emit-subx-stmt-list:continue/disp8
23402       }
23403       {
23404 $emit-subx-stmt-list:check-for-reg-var-def:
23405         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
23406         0f 85/jump-if-!= break/disp32
23407 $emit-subx-stmt-list:reg-var-def:
23408         # TODO: ensure that there's exactly one output
23409         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
23410         # emit the instruction as usual
23411         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
23412         #
23413         eb/jump $emit-subx-stmt-list:continue/disp8
23414       }
23415 $emit-subx-stmt-list:continue:
23416       # TODO: raise an error on unrecognized Stmt-tag
23417       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
23418       89/<- %esi 0/r32/eax
23419       e9/jump loop/disp32
23420     }
23421 $emit-subx-stmt-list:emit-cleanup:
23422     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
23423 $emit-subx-stmt-list:clean-up:
23424     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
23425     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
23426 $emit-subx-stmt-list:end:
23427     # . restore registers
23428     5e/pop-to-esi
23429     5b/pop-to-ebx
23430     59/pop-to-ecx
23431     58/pop-to-eax
23432     # . epilogue
23433     89/<- %esp 5/r32/ebp
23434     5d/pop-to-ebp
23435     c3/return
23436 
23437 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
23438 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)
23439     # . prologue
23440     55/push-ebp
23441     89/<- %ebp 4/r32/esp
23442     # . save registers
23443     50/push-eax
23444     51/push-ecx
23445     52/push-edx
23446     # ecx = stmt
23447     8b/-> *(ebp+0xc) 1/r32/ecx
23448     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
23449     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
23450     # TODO: assert !sv->is-deref?
23451     # var v/ecx: (addr var) = lookup(sv->value)
23452     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23453     89/<- %ecx 0/r32/eax
23454     # v->block-depth = *Curr-block-depth
23455     8b/-> *Curr-block-depth 0/r32/eax
23456     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
23457 #?     (write-buffered Stderr "var ")
23458 #?     (lookup *ecx *(ecx+4))
23459 #?     (write-buffered Stderr %eax)
23460 #?     (write-buffered Stderr " at depth ")
23461 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
23462 #?     (write-buffered Stderr Newline)
23463 #?     (flush Stderr)
23464     # ensure that v is in a register
23465     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23466     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
23467     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
23468     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
23469     89/<- %edx 0/r32/eax
23470     3d/compare-eax-and 0/imm32/false
23471     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
23472     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
23473     89/<- %edx 0/r32/eax
23474     # check emit-spill?
23475     3d/compare-eax-and 0/imm32/false
23476     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
23477     # TODO: assert(size-of(output) == 4)
23478     # *Curr-local-stack-offset -= 4
23479     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
23480     # emit spill
23481     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
23482     (emit-push-register *(ebp+8) %eax)
23483 $push-output-and-maybe-emit-spill:push:
23484     8b/-> *(ebp+0xc) 1/r32/ecx
23485     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
23486     # push(vars, {sv->value, emit-spill?})
23487     (push *(ebp+0x10) *eax)  # Stmt-var-value
23488     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
23489     (push *(ebp+0x10) %edx)
23490 $push-output-and-maybe-emit-spill:end:
23491     # . restore registers
23492     5a/pop-to-edx
23493     59/pop-to-ecx
23494     58/pop-to-eax
23495     # . epilogue
23496     89/<- %esp 5/r32/ebp
23497     5d/pop-to-ebp
23498     c3/return
23499 
23500 $push-output-and-maybe-emit-spill:abort:
23501     # error("var '" var->name "' initialized from an instruction must live in a register\n")
23502     (write-buffered *(ebp+0x1c) "var '")
23503     (write-buffered *(ebp+0x1c) *eax)  # Var-name
23504     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
23505     (flush *(ebp+0x1c))
23506     (stop *(ebp+0x20) 1)
23507     # never gets here
23508 
23509 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
23510     # . prologue
23511     55/push-ebp
23512     89/<- %ebp 4/r32/esp
23513     # . save registers
23514     50/push-eax
23515     51/push-ecx
23516     # ecx = stmt
23517     8b/-> *(ebp+0xc) 1/r32/ecx
23518     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
23519     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23520     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23521     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23522     # clean up until target block
23523     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
23524     # emit jump to target block
23525     (emit-indent *(ebp+8) *Curr-block-depth)
23526     (write-buffered *(ebp+8) "e9/jump ")
23527     (write-buffered *(ebp+8) %eax)
23528     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
23529     (string-starts-with? %eax "break")
23530     3d/compare-eax-and 0/imm32/false
23531     {
23532       74/jump-if-= break/disp8
23533       (write-buffered *(ebp+8) ":break/disp32\n")
23534       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
23535     }
23536     (write-buffered *(ebp+8) ":loop/disp32\n")
23537 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
23538     # . restore registers
23539     59/pop-to-ecx
23540     58/pop-to-eax
23541     # . epilogue
23542     89/<- %esp 5/r32/ebp
23543     5d/pop-to-ebp
23544     c3/return
23545 
23546 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
23547     # pseudocode:
23548     #   for every inout, output in return-stmt, fn->outputs
23549     #     if inout is a literal
23550     #       c7 0/subop/copy %output inout/imm32
23551     #     otherwise
23552     #       8b/-> inout %output
23553     #
23554     # . prologue
23555     55/push-ebp
23556     89/<- %ebp 4/r32/esp
23557     # . save registers
23558     50/push-eax
23559     51/push-ecx
23560     56/push-esi
23561     57/push-edi
23562     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
23563     8b/-> *(ebp+0xc) 0/r32/eax
23564     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23565     89/<- %esi 0/r32/eax
23566     # var curr-output/edi: (addr list var) = fn->outputs
23567     8b/-> *(ebp+0x10) 0/r32/eax
23568     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
23569     89/<- %edi 0/r32/eax
23570     {
23571 $emit-outputs:loop:
23572       81 7/subop/compare %esi 0/imm32
23573       0f 84/jump-if-= break/disp32
23574       # emit copy to output register
23575       # var curr-var/ecx = lookup(curr-inout->value)
23576       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23577       89/<- %ecx 0/r32/eax
23578       # if curr-var is a literal, emit copy of a literal to the output
23579       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23580       (is-simple-mu-type? %eax 0)  # literal => eax
23581       {
23582         3d/compare-eax-and 0/imm32/false
23583         0f 84/jump-if-= break/disp32
23584         (emit-indent *(ebp+8) *Curr-block-depth)
23585         (write-buffered *(ebp+8) "c7 0/subop/copy %")
23586         (lookup *edi *(edi+4))  # List-value List-value => eax
23587         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23588         (write-buffered *(ebp+8) %eax)
23589         (write-buffered *(ebp+8) " ")
23590         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23591         (write-buffered *(ebp+8) %eax)
23592         (write-buffered *(ebp+8) "/imm32\n")
23593         e9/jump $emit-outputs:continue/disp32
23594       }
23595       # if the non-literal is a register starting with "x", emit a floating-point copy
23596       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
23597       {
23598         3d/compare-eax-and 0/imm32
23599         0f 84/jump-if-= break/disp32
23600         8a/copy-byte *(eax+4) 0/r32/AL
23601         81 4/subop/and %eax 0xff/imm32
23602         3d/compare-eax-and 0x78/imm32/x
23603         0f 85/jump-if-!= break/disp32
23604         (emit-indent *(ebp+8) *Curr-block-depth)
23605         (write-buffered *(ebp+8) "f3 0f 10/->")
23606         (emit-subx-var-as-rm32 *(ebp+8) %esi)
23607         (write-buffered *(ebp+8) " ")
23608         (lookup *edi *(edi+4))  # List-value List-value => eax
23609         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23610         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
23611         (write-int32-hex-buffered *(ebp+8) *eax)
23612         (write-buffered *(ebp+8) "/x32\n")
23613         e9/jump $emit-outputs:continue/disp32
23614       }
23615       # otherwise emit an integer copy
23616       (emit-indent *(ebp+8) *Curr-block-depth)
23617       (write-buffered *(ebp+8) "8b/->")
23618       (emit-subx-var-as-rm32 *(ebp+8) %esi)
23619       (write-buffered *(ebp+8) " ")
23620       (lookup *edi *(edi+4))  # List-value List-value => eax
23621       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23622       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
23623       (write-int32-hex-buffered *(ebp+8) *eax)
23624       (write-buffered *(ebp+8) "/r32\n")
23625 $emit-outputs:continue:
23626       # curr-inout = curr-inout->next
23627       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23628       89/<- %esi 0/r32/eax
23629       # curr-output = curr-output->next
23630       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23631       89/<- %edi 0/r32/eax
23632       #
23633       e9/jump loop/disp32
23634     }
23635 $emit-outputs:end:
23636     # . restore registers
23637     5f/pop-to-edi
23638     5e/pop-to-esi
23639     59/pop-to-ecx
23640     58/pop-to-eax
23641     # . epilogue
23642     89/<- %esp 5/r32/ebp
23643     5d/pop-to-ebp
23644     c3/return
23645 
23646 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
23647     # . prologue
23648     55/push-ebp
23649     89/<- %ebp 4/r32/esp
23650     # . save registers
23651     51/push-ecx
23652     # ecx = lookup(stmt->operation)
23653     8b/-> *(ebp+8) 1/r32/ecx
23654     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
23655     89/<- %ecx 0/r32/eax
23656     # if (stmt->operation starts with "loop") return true
23657     (string-starts-with? %ecx "loop")  # => eax
23658     3d/compare-eax-and 0/imm32/false
23659     75/jump-if-not-equal $is-mu-branch?:end/disp8
23660     # if (stmt->operation starts with "break") return true
23661     (string-starts-with? %ecx "break")  # => eax
23662     3d/compare-eax-and 0/imm32/false
23663     75/jump-if-not-equal $is-mu-branch?:end/disp8
23664     # otherwise return (stmt->operation starts with "return")
23665     (string-starts-with? %ecx "return")  # => eax
23666 $is-mu-branch?:end:
23667     # . restore registers
23668     59/pop-to-ecx
23669     # . epilogue
23670     89/<- %esp 5/r32/ebp
23671     5d/pop-to-ebp
23672     c3/return
23673 
23674 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
23675     # . prologue
23676     55/push-ebp
23677     89/<- %ebp 4/r32/esp
23678     # . save registers
23679     50/push-eax
23680     # eax = stmt
23681     8b/-> *(ebp+0xc) 0/r32/eax
23682     #
23683     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23684     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
23685     (emit-indent *(ebp+8) *Curr-block-depth)
23686     (lookup *eax *(eax+4))  # => eax
23687     (write-buffered *(ebp+8) %eax)
23688     (write-buffered *(ebp+8) " break/disp32\n")
23689 $emit-reverse-break:end:
23690     # . restore registers
23691     58/pop-to-eax
23692     # . epilogue
23693     89/<- %esp 5/r32/ebp
23694     5d/pop-to-ebp
23695     c3/return
23696 
23697 == data
23698 
23699 # Table from Mu branch instructions to the reverse SubX opcodes for them.
23700 Reverse-branch:  # (table (handle array byte) (handle array byte))
23701   # a table is a stream
23702   0x1c0/imm32/write
23703   0/imm32/read
23704   0x1c0/imm32/size
23705   # data
23706   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
23707   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
23708   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
23709   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
23710   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
23711   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
23712   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
23713   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
23714   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
23715   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
23716   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
23717   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
23718   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
23719   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
23720   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
23721   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
23722   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
23723   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
23724   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
23725   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
23726   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
23727   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
23728   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
23729   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
23730   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
23731   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
23732   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
23733   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
23734 
23735 == code
23736 
23737 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
23738     # . prologue
23739     55/push-ebp
23740     89/<- %ebp 4/r32/esp
23741     # . save registers
23742     50/push-eax
23743     51/push-ecx
23744     52/push-edx
23745     53/push-ebx
23746     56/push-esi
23747     # ecx = vars
23748     8b/-> *(ebp+0xc) 1/r32/ecx
23749     # var eax: int = vars->top
23750     8b/-> *ecx 0/r32/eax
23751     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
23752     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
23753     # var min/ecx: (addr handle var) = vars->data
23754     8d/copy-address *(ecx+8) 1/r32/ecx
23755     # edx = depth
23756     8b/-> *(ebp+0x10) 2/r32/edx
23757     {
23758 $emit-unconditional-jump-to-depth:loop:
23759       # if (curr < min) break
23760       39/compare %esi 1/r32/ecx
23761       0f 82/jump-if-addr< break/disp32
23762       # var v/ebx: (addr var) = lookup(*curr)
23763       (lookup *esi *(esi+4))  # => eax
23764       89/<- %ebx 0/r32/eax
23765       # if (v->block-depth < until-block-depth) break
23766       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
23767       0f 8c/jump-if-< break/disp32
23768       {
23769 $emit-unconditional-jump-to-depth:check:
23770         # if v->block-depth != until-block-depth, continue
23771         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
23772         0f 85/jump-if-!= break/disp32
23773 $emit-unconditional-jump-to-depth:depth-found:
23774         # if v is not a literal, continue
23775         (size-of %ebx)  # => eax
23776         3d/compare-eax-and 0/imm32
23777         0f 85/jump-if-!= break/disp32
23778 $emit-unconditional-jump-to-depth:label-found:
23779         # emit unconditional jump, then return
23780         (emit-indent *(ebp+8) *Curr-block-depth)
23781         (write-buffered *(ebp+8) "e9/jump ")
23782         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
23783         (write-buffered *(ebp+8) %eax)
23784         (write-buffered *(ebp+8) ":")
23785         (write-buffered *(ebp+8) *(ebp+0x14))
23786         (write-buffered *(ebp+8) "/disp32\n")
23787         eb/jump $emit-unconditional-jump-to-depth:end/disp8
23788       }
23789       # curr -= 12
23790       81 5/subop/subtract %esi 0xc/imm32
23791       e9/jump loop/disp32
23792     }
23793     # TODO: error if no label at 'depth' was found
23794 $emit-unconditional-jump-to-depth:end:
23795     # . restore registers
23796     5e/pop-to-esi
23797     5b/pop-to-ebx
23798     5a/pop-to-edx
23799     59/pop-to-ecx
23800     58/pop-to-eax
23801     # . epilogue
23802     89/<- %esp 5/r32/ebp
23803     5d/pop-to-ebp
23804     c3/return
23805 
23806 # emit clean-up code for 'vars' until some block depth
23807 # doesn't actually modify 'vars' so we need traverse manually inside the stack
23808 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
23809     # . prologue
23810     55/push-ebp
23811     89/<- %ebp 4/r32/esp
23812     # . save registers
23813     50/push-eax
23814     51/push-ecx
23815     52/push-edx
23816     53/push-ebx
23817     56/push-esi
23818 #?     (write-buffered Stderr "--- cleanup\n")
23819 #?     (flush Stderr)
23820     # ecx = vars
23821     8b/-> *(ebp+0xc) 1/r32/ecx
23822     # var esi: int = vars->top
23823     8b/-> *ecx 6/r32/esi
23824     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
23825     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
23826     # var min/ecx: (addr handle var) = vars->data
23827     81 0/subop/add %ecx 8/imm32
23828     # edx = until-block-depth
23829     8b/-> *(ebp+0x10) 2/r32/edx
23830     {
23831 $emit-cleanup-code-until-depth:loop:
23832       # if (curr < min) break
23833       39/compare %esi 1/r32/ecx
23834       0f 82/jump-if-addr< break/disp32
23835       # var v/ebx: (addr var) = lookup(*curr)
23836       (lookup *esi *(esi+4))  # => eax
23837       89/<- %ebx 0/r32/eax
23838 #?       (lookup *ebx *(ebx+4))  # Var-name
23839 #?       (write-buffered Stderr "var ")
23840 #?       (write-buffered Stderr %eax)
23841 #?       (write-buffered Stderr Newline)
23842 #?       (flush Stderr)
23843       # if (v->block-depth < until-block-depth) break
23844       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
23845       0f 8c/jump-if-< break/disp32
23846       # if v is in a register
23847       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
23848       {
23849         0f 84/jump-if-= break/disp32
23850         {
23851 $emit-cleanup-code-until-depth:check-for-previous-spill:
23852           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
23853           3d/compare-eax-and 0/imm32/false
23854           74/jump-if-= break/disp8
23855 $emit-cleanup-code-until-depth:reclaim-var-in-register:
23856           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
23857           (emit-pop-register *(ebp+8) %eax)
23858         }
23859         eb/jump $emit-cleanup-code-until-depth:continue/disp8
23860       }
23861       # otherwise v is on the stack
23862       {
23863         75/jump-if-!= break/disp8
23864 $emit-cleanup-code-until-depth:var-on-stack:
23865         (size-of %ebx)  # => eax
23866         # don't emit code for labels
23867         3d/compare-eax-and 0/imm32
23868         74/jump-if-= break/disp8
23869 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
23870         (emit-indent *(ebp+8) *Curr-block-depth)
23871         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
23872         (write-int32-hex-buffered *(ebp+8) %eax)
23873         (write-buffered *(ebp+8) "/imm32\n")
23874       }
23875 $emit-cleanup-code-until-depth:continue:
23876       # curr -= 12
23877       81 5/subop/subtract %esi 0xc/imm32
23878       e9/jump loop/disp32
23879     }
23880 $emit-cleanup-code-until-depth:end:
23881     # . restore registers
23882     5e/pop-to-esi
23883     5b/pop-to-ebx
23884     5a/pop-to-edx
23885     59/pop-to-ecx
23886     58/pop-to-eax
23887     # . epilogue
23888     89/<- %esp 5/r32/ebp
23889     5d/pop-to-ebp
23890     c3/return
23891 
23892 # emit clean-up code for 'vars' that don't conflict with output registers
23893 # doesn't actually modify 'vars' so we need traverse manually inside the stack
23894 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
23895     # . prologue
23896     55/push-ebp
23897     89/<- %ebp 4/r32/esp
23898     # . save registers
23899     50/push-eax
23900     51/push-ecx
23901     52/push-edx
23902     53/push-ebx
23903     56/push-esi
23904     57/push-edi
23905     # ecx = vars
23906     8b/-> *(ebp+0xc) 1/r32/ecx
23907     # var esi: int = vars->top
23908     8b/-> *ecx 6/r32/esi
23909     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
23910     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
23911     # var min/ecx: (addr handle var) = vars->data
23912     81 0/subop/add %ecx 8/imm32
23913     {
23914 $emit-cleanup-code-for-non-outputs:loop:
23915       # if (curr < min) break
23916       39/compare %esi 1/r32/ecx
23917       0f 82/jump-if-addr< break/disp32
23918       # var v/ebx: (addr var) = lookup(*curr)
23919       (lookup *esi *(esi+4))  # => eax
23920       89/<- %ebx 0/r32/eax
23921       # if v is in a register
23922       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
23923       {
23924         0f 84/jump-if-= break/disp32
23925         {
23926 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
23927           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
23928           3d/compare-eax-and 0/imm32/false
23929           0f 84/jump-if-= break/disp32
23930 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
23931           # var reg/edi: (addr array name) = v->register
23932           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
23933           89/<- %edi 0/r32/eax
23934           # if reg is not in function outputs, emit a pop
23935           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
23936           3d/compare-eax-and 0/imm32/false
23937           {
23938             75/jump-if-!= break/disp8
23939             (emit-pop-register *(ebp+8) %edi)
23940             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
23941           }
23942           # otherwise just drop it from the stack
23943           (emit-indent *(ebp+8) *Curr-block-depth)
23944           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
23945         }
23946 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
23947         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
23948       }
23949       # otherwise v is on the stack
23950       {
23951         75/jump-if-!= break/disp8
23952 $emit-cleanup-code-for-non-outputs:var-on-stack:
23953         (size-of %ebx)  # => eax
23954         # don't emit code for labels
23955         3d/compare-eax-and 0/imm32
23956         74/jump-if-= break/disp8
23957 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
23958         (emit-indent *(ebp+8) *Curr-block-depth)
23959         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
23960         (write-int32-hex-buffered *(ebp+8) %eax)
23961         (write-buffered *(ebp+8) "/imm32\n")
23962       }
23963 $emit-cleanup-code-for-non-outputs:continue:
23964       # curr -= 12
23965       81 5/subop/subtract %esi 0xc/imm32
23966       e9/jump loop/disp32
23967     }
23968 $emit-cleanup-code-for-non-outputs:end:
23969     # . restore registers
23970     5f/pop-to-edi
23971     5e/pop-to-esi
23972     5b/pop-to-ebx
23973     5a/pop-to-edx
23974     59/pop-to-ecx
23975     58/pop-to-eax
23976     # . epilogue
23977     89/<- %esp 5/r32/ebp
23978     5d/pop-to-ebp
23979     c3/return
23980 
23981 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
23982     # . prologue
23983     55/push-ebp
23984     89/<- %ebp 4/r32/esp
23985     # eax = reg
23986     8b/-> *(ebp+0xc) 0/r32/eax
23987     # var prefix/eax: byte = reg->data[0]
23988     8a/copy-byte *(eax+4) 0/r32/AL
23989     81 4/subop/and %eax 0xff/imm32
23990     # if (prefix == 'x') push xmm register
23991     {
23992       3d/compare-eax-and 0x78/imm32/x
23993       0f 85/jump-if-!= break/disp32
23994       # TODO validate register
23995       (emit-indent *(ebp+8) *Curr-block-depth)
23996       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
23997       (emit-indent *(ebp+8) *Curr-block-depth)
23998       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
23999       # var prefix/eax: byte = reg->data[3]
24000       8b/-> *(ebp+0xc) 0/r32/eax
24001       8a/copy-byte *(eax+7) 0/r32/AL
24002       81 4/subop/and %eax 0xff/imm32
24003       (write-byte-buffered *(ebp+8) %eax)
24004       (write-buffered *(ebp+8) "/x32\n")
24005       e9/jump $emit-push-register:end/disp32
24006     }
24007     # otherwise push gp register
24008     (emit-indent *(ebp+8) *Curr-block-depth)
24009     (write-buffered *(ebp+8) "ff 6/subop/push %")
24010     (write-buffered *(ebp+8) *(ebp+0xc))
24011     (write-buffered *(ebp+8) Newline)
24012 $emit-push-register:end:
24013     # . epilogue
24014     89/<- %esp 5/r32/ebp
24015     5d/pop-to-ebp
24016     c3/return
24017 
24018 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
24019     # . prologue
24020     55/push-ebp
24021     89/<- %ebp 4/r32/esp
24022     # . save registers
24023     50/push-eax
24024     # eax = reg
24025     8b/-> *(ebp+0xc) 0/r32/eax
24026     # var prefix/eax: byte = reg->data[0]
24027     8a/copy-byte *(eax+4) 0/r32/AL
24028     81 4/subop/and %eax 0xff/imm32
24029     # if (prefix == 'x') pop to xmm register
24030     {
24031       3d/compare-eax-and 0x78/imm32/x
24032       0f 85/jump-if-!= break/disp32
24033       # TODO validate register
24034       (emit-indent *(ebp+8) *Curr-block-depth)
24035       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
24036       # var prefix/eax: byte = reg->data[3]
24037       8b/-> *(ebp+0xc) 0/r32/eax
24038       8a/copy-byte *(eax+7) 0/r32/AL
24039       81 4/subop/and %eax 0xff/imm32
24040       (write-byte-buffered *(ebp+8) %eax)
24041       (write-buffered *(ebp+8) "/x32\n")
24042       (emit-indent *(ebp+8) *Curr-block-depth)
24043       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
24044       e9/jump $emit-pop-register:end/disp32
24045     }
24046     # otherwise pop to gp register
24047     (emit-indent *(ebp+8) *Curr-block-depth)
24048     (write-buffered *(ebp+8) "8f 0/subop/pop %")
24049     (write-buffered *(ebp+8) *(ebp+0xc))
24050     (write-buffered *(ebp+8) Newline)
24051 $emit-pop-register:end:
24052     # . restore registers
24053     58/pop-to-eax
24054     # . epilogue
24055     89/<- %esp 5/r32/ebp
24056     5d/pop-to-ebp
24057     c3/return
24058 
24059 # emit clean-up code for 'vars' until a given label is encountered
24060 # doesn't actually modify 'vars' so we need traverse manually inside the stack
24061 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
24062     # . prologue
24063     55/push-ebp
24064     89/<- %ebp 4/r32/esp
24065     # . save registers
24066     50/push-eax
24067     51/push-ecx
24068     52/push-edx
24069     53/push-ebx
24070     # ecx = vars
24071     8b/-> *(ebp+0xc) 1/r32/ecx
24072     # var eax: int = vars->top
24073     8b/-> *ecx 0/r32/eax
24074     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
24075     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
24076     # var min/ecx: (addr handle var) = vars->data
24077     81 0/subop/add %ecx 8/imm32
24078     {
24079 $emit-cleanup-code-until-target:loop:
24080       # if (curr < min) break
24081       39/compare %edx 1/r32/ecx
24082       0f 82/jump-if-addr< break/disp32
24083       # var v/ebx: (handle var) = lookup(*curr)
24084       (lookup *edx *(edx+4))  # => eax
24085       89/<- %ebx 0/r32/eax
24086       # if (v->name == until-block-label) break
24087       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
24088       (string-equal? %eax *(ebp+0x10))  # => eax
24089       3d/compare-eax-and 0/imm32/false
24090       0f 85/jump-if-!= break/disp32
24091       # if v is in a register
24092       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
24093       {
24094         0f 84/jump-if-= break/disp32
24095         {
24096 $emit-cleanup-code-until-target:check-for-previous-spill:
24097           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
24098           3d/compare-eax-and 0/imm32/false
24099           74/jump-if-= break/disp8
24100 $emit-cleanup-code-until-target:reclaim-var-in-register:
24101           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
24102           (emit-pop-register *(ebp+8) %eax)
24103         }
24104         eb/jump $emit-cleanup-code-until-target:continue/disp8
24105       }
24106       # otherwise v is on the stack
24107       {
24108         75/jump-if-!= break/disp8
24109 $emit-cleanup-code-until-target:reclaim-var-on-stack:
24110         (size-of %ebx)  # => eax
24111         # don't emit code for labels
24112         3d/compare-eax-and 0/imm32
24113         74/jump-if-= break/disp8
24114         #
24115         (emit-indent *(ebp+8) *Curr-block-depth)
24116         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
24117         (write-int32-hex-buffered *(ebp+8) %eax)
24118         (write-buffered *(ebp+8) "/imm32\n")
24119       }
24120 $emit-cleanup-code-until-target:continue:
24121       # curr -= 12
24122       81 5/subop/subtract %edx 0xc/imm32
24123       e9/jump loop/disp32
24124     }
24125 $emit-cleanup-code-until-target:end:
24126     # . restore registers
24127     5b/pop-to-ebx
24128     5a/pop-to-edx
24129     59/pop-to-ecx
24130     58/pop-to-eax
24131     # . epilogue
24132     89/<- %esp 5/r32/ebp
24133     5d/pop-to-ebp
24134     c3/return
24135 
24136 # update Curr-local-stack-offset assuming vars until some block depth are popped
24137 # doesn't actually modify 'vars', so we need traverse manually inside the stack
24138 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
24139     # . prologue
24140     55/push-ebp
24141     89/<- %ebp 4/r32/esp
24142     # . save registers
24143     50/push-eax
24144     51/push-ecx
24145     52/push-edx
24146     53/push-ebx
24147     56/push-esi
24148     # ecx = vars
24149     8b/-> *(ebp+8) 1/r32/ecx
24150     # var esi: int = vars->top
24151     8b/-> *ecx 6/r32/esi
24152     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
24153     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
24154     # var min/ecx: (addr handle var) = vars->data
24155     81 0/subop/add %ecx 8/imm32
24156     # edx = until-block-depth
24157     8b/-> *(ebp+0xc) 2/r32/edx
24158     {
24159 $clean-up-stack-offset-state:loop:
24160       # if (curr < min) break
24161       39/compare %esi 1/r32/ecx
24162       0f 82/jump-if-addr< break/disp32
24163       # var v/ebx: (addr var) = lookup(*curr)
24164       (lookup *esi *(esi+4))  # => eax
24165       89/<- %ebx 0/r32/eax
24166       # if (v->block-depth < until-block-depth) break
24167       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
24168       0f 8c/jump-if-< break/disp32
24169       # if v is in a register
24170       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
24171       {
24172         0f 84/jump-if-= break/disp32
24173         {
24174 $clean-up-stack-offset-state:check-for-previous-spill:
24175           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
24176           3d/compare-eax-and 0/imm32/false
24177           74/jump-if-= break/disp8
24178 $clean-up-stack-offset-state:reclaim-var-in-register:
24179           81 0/subop/add *Curr-local-stack-offset 4/imm32
24180         }
24181         eb/jump $clean-up-stack-offset-state:continue/disp8
24182       }
24183       # otherwise v is on the stack
24184       {
24185         75/jump-if-!= break/disp8
24186 $clean-up-stack-offset-state:var-on-stack:
24187         (size-of %ebx)  # => eax
24188         01/add-to *Curr-local-stack-offset 0/r32/eax
24189       }
24190 $clean-up-stack-offset-state:continue:
24191       # curr -= 12
24192       81 5/subop/subtract %esi 0xc/imm32
24193       e9/jump loop/disp32
24194     }
24195 $clean-up-stack-offset-state:end:
24196     # . restore registers
24197     5e/pop-to-esi
24198     5b/pop-to-ebx
24199     5a/pop-to-edx
24200     59/pop-to-ecx
24201     58/pop-to-eax
24202     # . epilogue
24203     89/<- %esp 5/r32/ebp
24204     5d/pop-to-ebp
24205     c3/return
24206 
24207 # Return true if there isn't a variable in 'vars' with the same block-depth
24208 # and register as 'v'.
24209 # 'v' is guaranteed not to be within 'vars'.
24210 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
24211     # . prologue
24212     55/push-ebp
24213     89/<- %ebp 4/r32/esp
24214     # . save registers
24215     51/push-ecx
24216     52/push-edx
24217     53/push-ebx
24218     56/push-esi
24219     57/push-edi
24220     # ecx = vars
24221     8b/-> *(ebp+0xc) 1/r32/ecx
24222     # var eax: int = vars->top
24223     8b/-> *ecx 0/r32/eax
24224     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
24225     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
24226     # var min/ecx: (addr handle var) = vars->data
24227     8d/copy-address *(ecx+8) 1/r32/ecx
24228     # var depth/ebx: int = v->block-depth
24229     8b/-> *(ebp+8) 3/r32/ebx
24230     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
24231     # var needle/esi: (addr array byte) = v->register
24232     8b/-> *(ebp+8) 6/r32/esi
24233     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
24234     89/<- %esi 0/r32/eax
24235     {
24236 $not-yet-spilled-this-block?:loop:
24237       # if (curr < min) break
24238       39/compare %edx 1/r32/ecx
24239       0f 82/jump-if-addr< break/disp32
24240       # var cand/edi: (addr var) = lookup(*curr)
24241       (lookup *edx *(edx+4))  # => eax
24242       89/<- %edi 0/r32/eax
24243       # if (cand->block-depth < depth) break
24244       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
24245       0f 8c/jump-if-< break/disp32
24246       # var cand-reg/edi: (array array byte) = cand->reg
24247       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
24248       89/<- %edi 0/r32/eax
24249       # if (cand-reg == null) continue
24250       {
24251 $not-yet-spilled-this-block?:check-reg:
24252         81 7/subop/compare %edi 0/imm32
24253         0f 84/jump-if-= break/disp32
24254         # if (cand-reg == needle) return true
24255         (string-equal? %esi %edi)  # => eax
24256         3d/compare-eax-and 0/imm32/false
24257         74/jump-if-= break/disp8
24258 $not-yet-spilled-this-block?:return-false:
24259         b8/copy-to-eax 0/imm32/false
24260         eb/jump $not-yet-spilled-this-block?:end/disp8
24261       }
24262 $not-yet-spilled-this-block?:continue:
24263       # curr -= 12
24264       81 5/subop/subtract %edx 0xc/imm32
24265       e9/jump loop/disp32
24266     }
24267 $not-yet-spilled-this-block?:return-true:
24268     # return true
24269     b8/copy-to-eax 1/imm32/true
24270 $not-yet-spilled-this-block?:end:
24271     # . restore registers
24272     5f/pop-to-edi
24273     5e/pop-to-esi
24274     5b/pop-to-ebx
24275     5a/pop-to-edx
24276     59/pop-to-ecx
24277     # . epilogue
24278     89/<- %esp 5/r32/ebp
24279     5d/pop-to-ebp
24280     c3/return
24281 
24282 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
24283 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
24284     # . prologue
24285     55/push-ebp
24286     89/<- %ebp 4/r32/esp
24287     # eax = v
24288     8b/-> *(ebp+8) 0/r32/eax
24289     # var reg/eax: (addr array byte) = lookup(v->register)
24290     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24291     # var target/eax: (addr var) = find-register(fn-outputs, reg)
24292     (find-register *(ebp+0x10) %eax)  # => eax
24293     # if (target == 0) return true
24294     {
24295       3d/compare-eax-and 0/imm32
24296       75/jump-if-!= break/disp8
24297       b8/copy-to-eax 1/imm32/true
24298       eb/jump $will-not-write-some-register?:end/disp8
24299     }
24300     # return !assigns-in-stmts?(stmts, target)
24301     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
24302     3d/compare-eax-and 0/imm32/false
24303     # assume: true = 1, so no need to mask with 0x000000ff
24304     0f 94/set-if-= %al
24305 $will-not-write-some-register?:end:
24306     # . epilogue
24307     89/<- %esp 5/r32/ebp
24308     5d/pop-to-ebp
24309     c3/return
24310 
24311 # return fn output with matching register
24312 # always returns false if 'reg' is null
24313 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
24314     # . prologue
24315     55/push-ebp
24316     89/<- %ebp 4/r32/esp
24317     # . save registers
24318     51/push-ecx
24319     # var curr/ecx: (addr list var) = lookup(fn->outputs)
24320     8b/-> *(ebp+8) 1/r32/ecx
24321     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
24322     89/<- %ecx 0/r32/eax
24323     {
24324 $find-register:loop:
24325       # if (curr == 0) break
24326       81 7/subop/compare %ecx 0/imm32
24327       74/jump-if-= break/disp8
24328       # eax = curr->value->register
24329       (lookup *ecx *(ecx+4))  # List-value List-value => eax
24330       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24331       # if (eax == reg) return curr->value
24332 $find-register:compare:
24333       (string-equal? *(ebp+0xc) %eax)  # => eax
24334       {
24335         3d/compare-eax-and 0/imm32/false
24336         74/jump-if-= break/disp8
24337 $find-register:found:
24338         (lookup *ecx *(ecx+4))  # List-value List-value => eax
24339         eb/jump $find-register:end/disp8
24340       }
24341       # curr = lookup(curr->next)
24342       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
24343       89/<- %ecx 0/r32/eax
24344       #
24345       eb/jump loop/disp8
24346     }
24347 $find-register:end:
24348     # . restore registers
24349     59/pop-to-ecx
24350     # . epilogue
24351     89/<- %esp 5/r32/ebp
24352     5d/pop-to-ebp
24353     c3/return
24354 
24355 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
24356     # . prologue
24357     55/push-ebp
24358     89/<- %ebp 4/r32/esp
24359     # . save registers
24360     51/push-ecx
24361     # var curr/ecx: (addr list stmt) = stmts
24362     8b/-> *(ebp+8) 1/r32/ecx
24363     {
24364       # if (curr == 0) break
24365       81 7/subop/compare %ecx 0/imm32
24366       74/jump-if-= break/disp8
24367       # if assigns-in-stmt?(curr->value, v) return true
24368       (lookup *ecx *(ecx+4))  # List-value List-value => eax
24369       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
24370       3d/compare-eax-and 0/imm32/false
24371       75/jump-if-!= break/disp8
24372       # curr = lookup(curr->next)
24373       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
24374       89/<- %ecx 0/r32/eax
24375       #
24376       eb/jump loop/disp8
24377     }
24378 $assigns-in-stmts?:end:
24379     # . restore registers
24380     59/pop-to-ecx
24381     # . epilogue
24382     89/<- %esp 5/r32/ebp
24383     5d/pop-to-ebp
24384     c3/return
24385 
24386 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
24387     # . prologue
24388     55/push-ebp
24389     89/<- %ebp 4/r32/esp
24390     # . save registers
24391     51/push-ecx
24392     # ecx = stmt
24393     8b/-> *(ebp+8) 1/r32/ecx
24394     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
24395     {
24396       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
24397       75/jump-if-!= break/disp8
24398       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24399       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
24400       eb/jump $assigns-in-stmt?:end/disp8
24401     }
24402     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
24403     {
24404       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
24405       75/jump-if-!= break/disp8
24406       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
24407       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
24408       eb/jump $assigns-in-stmt?:end/disp8
24409     }
24410     # otherwise return false
24411     b8/copy 0/imm32/false
24412 $assigns-in-stmt?:end:
24413     # . restore registers
24414     59/pop-to-ecx
24415     # . epilogue
24416     89/<- %esp 5/r32/ebp
24417     5d/pop-to-ebp
24418     c3/return
24419 
24420 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
24421     # . prologue
24422     55/push-ebp
24423     89/<- %ebp 4/r32/esp
24424     # . save registers
24425     51/push-ecx
24426     # var curr/ecx: (addr stmt-var) = stmt-var
24427     8b/-> *(ebp+8) 1/r32/ecx
24428     {
24429       # if (curr == 0) break
24430       81 7/subop/compare %ecx 0/imm32
24431       74/jump-if-= break/disp8
24432       # eax = lookup(curr->value)
24433       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24434       # if (eax == v  &&  curr->is-deref? == false) return true
24435       {
24436         39/compare *(ebp+0xc) 0/r32/eax
24437         75/jump-if-!= break/disp8
24438         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
24439         75/jump-if-!= break/disp8
24440         b8/copy-to-eax 1/imm32/true
24441         eb/jump $assigns-in-stmt-vars?:end/disp8
24442       }
24443       # curr = lookup(curr->next)
24444       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24445       89/<- %ecx 0/r32/eax
24446       #
24447       eb/jump loop/disp8
24448     }
24449 $assigns-in-stmt-vars?:end:
24450     # . restore registers
24451     59/pop-to-ecx
24452     # . epilogue
24453     89/<- %esp 5/r32/ebp
24454     5d/pop-to-ebp
24455     c3/return
24456 
24457 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
24458 # v is guaranteed to be within vars
24459 # 'start' is provided as an optimization, a pointer within vars
24460 # *start == v
24461 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
24462     # . prologue
24463     55/push-ebp
24464     89/<- %ebp 4/r32/esp
24465     # . save registers
24466     51/push-ecx
24467     52/push-edx
24468     53/push-ebx
24469     56/push-esi
24470     57/push-edi
24471     # ecx = v
24472     8b/-> *(ebp+8) 1/r32/ecx
24473     # var reg/edx: (addr array byte) = lookup(v->register)
24474     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
24475     89/<- %edx 0/r32/eax
24476     # var depth/ebx: int = v->block-depth
24477     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
24478     # var min/ecx: (addr handle var) = vars->data
24479     8b/-> *(ebp+0xc) 1/r32/ecx
24480     81 0/subop/add %ecx 8/imm32
24481     # TODO: check that start >= min and start < &vars->data[top]
24482     # TODO: check that *start == v
24483     # var curr/esi: (addr handle var) = start
24484     8b/-> *(ebp+0x10) 6/r32/esi
24485     # curr -= 8
24486     81 5/subop/subtract %esi 8/imm32
24487     {
24488 $same-register-spilled-before?:loop:
24489       # if (curr < min) break
24490       39/compare %esi 1/r32/ecx
24491       0f 82/jump-if-addr< break/disp32
24492       # var x/eax: (addr var) = lookup(*curr)
24493       (lookup *esi *(esi+4))  # => eax
24494       # if (x->block-depth < depth) break
24495       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
24496       0f 8c/jump-if-< break/disp32
24497       # if (x->register == 0) continue
24498       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
24499       74/jump-if-= $same-register-spilled-before?:continue/disp8
24500       # if (x->register == reg) return true
24501       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24502       (string-equal? %eax %edx)  # => eax
24503       3d/compare-eax-and 0/imm32/false
24504       b8/copy-to-eax 1/imm32/true
24505       75/jump-if-!= $same-register-spilled-before?:end/disp8
24506 $same-register-spilled-before?:continue:
24507       # curr -= 8
24508       81 5/subop/subtract %esi 8/imm32
24509       e9/jump loop/disp32
24510     }
24511 $same-register-spilled-before?:false:
24512     b8/copy-to-eax 0/imm32/false
24513 $same-register-spilled-before?:end:
24514     # . restore registers
24515     5f/pop-to-edi
24516     5e/pop-to-esi
24517     5b/pop-to-ebx
24518     5a/pop-to-edx
24519     59/pop-to-ecx
24520     # . epilogue
24521     89/<- %esp 5/r32/ebp
24522     5d/pop-to-ebp
24523     c3/return
24524 
24525 # clean up global state for 'vars' until some block depth (inclusive)
24526 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
24527     # . prologue
24528     55/push-ebp
24529     89/<- %ebp 4/r32/esp
24530     # . save registers
24531     50/push-eax
24532     51/push-ecx
24533     56/push-esi
24534     # esi = vars
24535     8b/-> *(ebp+8) 6/r32/esi
24536     # ecx = until-block-depth
24537     8b/-> *(ebp+0xc) 1/r32/ecx
24538     {
24539 $clean-up-blocks:reclaim-loop:
24540       # if (vars->top <= 0) break
24541       8b/-> *esi 0/r32/eax  # Stack-top
24542       3d/compare-eax-and 0/imm32
24543       0f 8e/jump-if-<= break/disp32
24544       # var v/eax: (addr var) = lookup(vars[vars->top-12])
24545       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
24546       # if (v->block-depth < until-block-depth) break
24547       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
24548       0f 8c/jump-if-< break/disp32
24549       (pop %esi)  # => eax
24550       (pop %esi)  # => eax
24551       (pop %esi)  # => eax
24552       e9/jump loop/disp32
24553     }
24554 $clean-up-blocks:end:
24555     # . restore registers
24556     5e/pop-to-esi
24557     59/pop-to-ecx
24558     58/pop-to-eax
24559     # . epilogue
24560     89/<- %esp 5/r32/ebp
24561     5d/pop-to-ebp
24562     c3/return
24563 
24564 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
24565     # . prologue
24566     55/push-ebp
24567     89/<- %ebp 4/r32/esp
24568     # . save registers
24569     51/push-ecx
24570     # var curr/ecx: (addr list var) = lookup(fn->outputs)
24571     8b/-> *(ebp+8) 0/r32/eax
24572     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
24573     89/<- %ecx 0/r32/eax
24574     # while curr != null
24575     {
24576       81 7/subop/compare %ecx 0/imm32
24577       74/jump-if-= break/disp8
24578       # var v/eax: (addr var) = lookup(curr->value)
24579       (lookup *ecx *(ecx+4))  # List-value List-value => eax
24580       # var reg/eax: (addr array byte) = lookup(v->register)
24581       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24582       # if (reg == target) return true
24583       (string-equal? %eax *(ebp+0xc))  # => eax
24584       3d/compare-eax-and 0/imm32/false
24585       75/jump-if-!= $reg-in-function-outputs?:end/disp8
24586       # curr = curr->next
24587       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
24588       89/<- %ecx 0/r32/eax
24589       #
24590       eb/jump loop/disp8
24591     }
24592     # return false
24593     b8/copy-to-eax 0/imm32
24594 $reg-in-function-outputs?:end:
24595     # . restore registers
24596     59/pop-to-ecx
24597     # . epilogue
24598     89/<- %esp 5/r32/ebp
24599     5d/pop-to-ebp
24600     c3/return
24601 
24602 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
24603     # . prologue
24604     55/push-ebp
24605     89/<- %ebp 4/r32/esp
24606     # . save registers
24607     50/push-eax
24608     51/push-ecx
24609     52/push-edx
24610     # eax = stmt
24611     8b/-> *(ebp+0xc) 0/r32/eax
24612     # var v/ecx: (addr var)
24613     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
24614     89/<- %ecx 0/r32/eax
24615     # v->block-depth = *Curr-block-depth
24616     8b/-> *Curr-block-depth 0/r32/eax
24617     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
24618     # var n/edx: int = size-of(stmt->var)
24619     (size-of %ecx)  # => eax
24620     89/<- %edx 0/r32/eax
24621     # *Curr-local-stack-offset -= n
24622     29/subtract-from *Curr-local-stack-offset 2/r32/edx
24623     # v->offset = *Curr-local-stack-offset
24624     8b/-> *Curr-local-stack-offset 0/r32/eax
24625     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
24626     # if v is an array, do something special to initialize it
24627     {
24628       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24629       (is-mu-array? %eax)  # => eax
24630       3d/compare-eax-and 0/imm32/false
24631       0f 84/jump-if-= break/disp32
24632       # var array-size-without-size/edx: int = n-4
24633       81 5/subop/subtract %edx 4/imm32
24634       #
24635       (emit-array-data-initialization *(ebp+8) %edx)
24636       e9/jump $emit-subx-var-def:end/disp32
24637     }
24638     # another special-case for initializing streams
24639     # a stream is an array with 2 extra pointers
24640     {
24641       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24642       (is-mu-stream? %eax)  # => eax
24643       3d/compare-eax-and 0/imm32/false
24644       0f 84/jump-if-= break/disp32
24645       # var array-size-without-size/edx: int = n-12
24646       81 5/subop/subtract %edx 0xc/imm32
24647       (emit-array-data-initialization *(ebp+8) %edx)
24648       # emit read and write pointers
24649       (emit-indent *(ebp+8) *Curr-block-depth)
24650       (write-buffered *(ebp+8) "68/push 0/imm32\n")
24651       (emit-indent *(ebp+8) *Curr-block-depth)
24652       (write-buffered *(ebp+8) "68/push 0/imm32\n")
24653       #
24654       eb/jump $emit-subx-var-def:end/disp8
24655     }
24656     # while n > 0
24657     {
24658       81 7/subop/compare %edx 0/imm32
24659       7e/jump-if-<= break/disp8
24660       (emit-indent *(ebp+8) *Curr-block-depth)
24661       (write-buffered *(ebp+8) "68/push 0/imm32\n")
24662       # n -= 4
24663       81 5/subop/subtract %edx 4/imm32
24664       #
24665       eb/jump loop/disp8
24666     }
24667 $emit-subx-var-def:end:
24668     # . restore registers
24669     5a/pop-to-edx
24670     59/pop-to-ecx
24671     58/pop-to-eax
24672     # . epilogue
24673     89/<- %esp 5/r32/ebp
24674     5d/pop-to-ebp
24675     c3/return
24676 
24677 emit-array-data-initialization:  # out: (addr buffered-file), n: int
24678     # . prologue
24679     55/push-ebp
24680     89/<- %ebp 4/r32/esp
24681     #
24682     (emit-indent *(ebp+8) *Curr-block-depth)
24683     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
24684     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
24685     (write-buffered *(ebp+8) ")\n")
24686     (emit-indent *(ebp+8) *Curr-block-depth)
24687     (write-buffered *(ebp+8) "68/push ")
24688     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
24689     (write-buffered *(ebp+8) "/imm32\n")
24690 $emit-array-data-initialization:end:
24691     # . epilogue
24692     89/<- %esp 5/r32/ebp
24693     5d/pop-to-ebp
24694     c3/return
24695 
24696 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
24697     # . prologue
24698     55/push-ebp
24699     89/<- %ebp 4/r32/esp
24700     # . save registers
24701     50/push-eax
24702     51/push-ecx
24703     # - some special-case primitives that don't actually use the 'primitives' data structure
24704     # var op/ecx: (addr array byte) = lookup(stmt->operation)
24705     8b/-> *(ebp+0xc) 1/r32/ecx
24706     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
24707     89/<- %ecx 0/r32/eax
24708     # array size
24709     {
24710       # if (!string-equal?(stmt->operation, "length")) break
24711       (string-equal? %ecx "length")  # => eax
24712       3d/compare-eax-and 0/imm32
24713       0f 84/jump-if-= break/disp32
24714       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24715       e9/jump $emit-subx-stmt:end/disp32
24716     }
24717     # index into array
24718     {
24719       # if (!string-equal?(stmt->operation, "index")) break
24720       (string-equal? %ecx "index")  # => eax
24721       3d/compare-eax-and 0/imm32
24722       0f 84/jump-if-= break/disp32
24723       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24724       e9/jump $emit-subx-stmt:end/disp32
24725     }
24726     # compute-offset for index into array
24727     {
24728       # if (!string-equal?(stmt->operation, "compute-offset")) break
24729       (string-equal? %ecx "compute-offset")  # => eax
24730       3d/compare-eax-and 0/imm32
24731       0f 84/jump-if-= break/disp32
24732       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24733       e9/jump $emit-subx-stmt:end/disp32
24734     }
24735     # get field from record
24736     {
24737       # if (!string-equal?(stmt->operation, "get")) break
24738       (string-equal? %ecx "get")  # => eax
24739       3d/compare-eax-and 0/imm32
24740       0f 84/jump-if-= break/disp32
24741       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
24742       e9/jump $emit-subx-stmt:end/disp32
24743     }
24744     # allocate scalar
24745     {
24746       # if (!string-equal?(stmt->operation, "allocate")) break
24747       (string-equal? %ecx "allocate")  # => eax
24748       3d/compare-eax-and 0/imm32
24749       0f 84/jump-if-= break/disp32
24750       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24751       e9/jump $emit-subx-stmt:end/disp32
24752     }
24753     # copy-object
24754     {
24755       # if (!string-equal?(stmt->operation, "copy-object")) break
24756       (string-equal? %ecx "copy-object")  # => eax
24757       3d/compare-eax-and 0/imm32
24758       0f 84/jump-if-= break/disp32
24759       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24760       e9/jump $emit-subx-stmt:end/disp32
24761     }
24762     # allocate array
24763     {
24764       # if (!string-equal?(stmt->operation, "populate")) break
24765       (string-equal? %ecx "populate")  # => eax
24766       3d/compare-eax-and 0/imm32
24767       0f 84/jump-if-= break/disp32
24768       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24769       e9/jump $emit-subx-stmt:end/disp32
24770     }
24771     # allocate stream
24772     {
24773       # if (!string-equal?(stmt->operation, "populate-stream")) break
24774       (string-equal? %ecx "populate-stream")  # => eax
24775       3d/compare-eax-and 0/imm32
24776       0f 84/jump-if-= break/disp32
24777       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24778       e9/jump $emit-subx-stmt:end/disp32
24779     }
24780     # read from stream
24781     {
24782       # if (!string-equal?(stmt->operation, "read-from-stream")) break
24783       (string-equal? %ecx "read-from-stream")  # => eax
24784       3d/compare-eax-and 0/imm32
24785       0f 84/jump-if-= break/disp32
24786       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24787       e9/jump $emit-subx-stmt:end/disp32
24788     }
24789     # write to stream
24790     {
24791       # if (!string-equal?(stmt->operation, "write-to-stream")) break
24792       (string-equal? %ecx "write-to-stream")  # => eax
24793       3d/compare-eax-and 0/imm32
24794       0f 84/jump-if-= break/disp32
24795       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
24796       e9/jump $emit-subx-stmt:end/disp32
24797     }
24798     # - if stmt matches a primitive, emit it
24799     {
24800 $emit-subx-stmt:check-for-primitive:
24801       # var curr/eax: (addr primitive)
24802       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
24803       3d/compare-eax-and 0/imm32
24804       74/jump-if-= break/disp8
24805 $emit-subx-stmt:primitive:
24806       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
24807       e9/jump $emit-subx-stmt:end/disp32
24808     }
24809     # - otherwise emit a call
24810     # TODO: type-checking
24811 $emit-subx-stmt:call:
24812     (emit-call *(ebp+8) *(ebp+0xc))
24813 $emit-subx-stmt:end:
24814     # . restore registers
24815     59/pop-to-ecx
24816     58/pop-to-eax
24817     # . epilogue
24818     89/<- %esp 5/r32/ebp
24819     5d/pop-to-ebp
24820     c3/return
24821 
24822 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
24823     # . prologue
24824     55/push-ebp
24825     89/<- %ebp 4/r32/esp
24826     # . save registers
24827     50/push-eax
24828     51/push-ecx
24829     52/push-edx
24830     53/push-ebx
24831     56/push-esi
24832     # esi = stmt
24833     8b/-> *(ebp+0xc) 6/r32/esi
24834     # var base/ebx: (addr var) = stmt->inouts[0]->value
24835     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24836     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24837     89/<- %ebx 0/r32/eax
24838     # var elemsize/ecx: int = array-element-size(base)
24839     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
24840     89/<- %ecx 0/r32/eax
24841     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
24842     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24843     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24844     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24845     89/<- %edx 0/r32/eax
24846     # if elemsize == 1
24847     {
24848       81 7/subop/compare %ecx 1/imm32
24849       75/jump-if-!= break/disp8
24850 $translate-mu-length-stmt:size-1:
24851       (emit-save-size-to *(ebp+8) %ebx %edx)
24852       e9/jump $translate-mu-length-stmt:end/disp32
24853     }
24854     # if elemsize is a power of 2 less than 256
24855     {
24856       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
24857       3d/compare-eax-and 0/imm32/false
24858       74/jump-if-= break/disp8
24859       81 7/subop/compare %ecx 0xff/imm32
24860       7f/jump-if-> break/disp8
24861 $translate-mu-length-stmt:size-power-of-2:
24862       (emit-save-size-to *(ebp+8) %ebx %edx)
24863       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
24864       e9/jump $translate-mu-length-stmt:end/disp32
24865     }
24866     # otherwise, the complex case
24867     # . emit register spills
24868     {
24869 $translate-mu-length-stmt:complex:
24870       (string-equal? %edx "eax")  # => eax
24871       3d/compare-eax-and 0/imm32/false
24872       75/break-if-!= break/disp8
24873       (emit-indent *(ebp+8) *Curr-block-depth)
24874       (write-buffered *(ebp+8) "50/push-eax\n")
24875     }
24876     {
24877       (string-equal? %edx "ecx")  # => eax
24878       3d/compare-eax-and 0/imm32/false
24879       75/break-if-!= break/disp8
24880       (emit-indent *(ebp+8) *Curr-block-depth)
24881       (write-buffered *(ebp+8) "51/push-ecx\n")
24882     }
24883     {
24884       (string-equal? %edx "edx")  # => eax
24885       3d/compare-eax-and 0/imm32/false
24886       75/break-if-!= break/disp8
24887       (emit-indent *(ebp+8) *Curr-block-depth)
24888       (write-buffered *(ebp+8) "52/push-edx\n")
24889     }
24890     # .
24891     (emit-save-size-to *(ebp+8) %ebx "eax")
24892     (emit-indent *(ebp+8) *Curr-block-depth)
24893     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
24894     (emit-indent *(ebp+8) *Curr-block-depth)
24895     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
24896     (write-int32-hex-buffered *(ebp+8) %ecx)
24897     (write-buffered *(ebp+8) "/imm32\n")
24898     (emit-indent *(ebp+8) *Curr-block-depth)
24899     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
24900     {
24901       (string-equal? %edx "eax")  # => eax
24902       3d/compare-eax-and 0/imm32/false
24903       75/break-if-!= break/disp8
24904       (emit-indent *(ebp+8) *Curr-block-depth)
24905       (write-buffered *(ebp+8) "89/<- %")
24906       (write-buffered *(ebp+8) %edx)
24907       (write-buffered *(ebp+8) " 0/r32/eax\n")
24908     }
24909     # . emit register restores
24910     {
24911       (string-equal? %edx "edx")  # => eax
24912       3d/compare-eax-and 0/imm32/false
24913       75/break-if-!= break/disp8
24914       (emit-indent *(ebp+8) *Curr-block-depth)
24915       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
24916     }
24917     {
24918       (string-equal? %edx "ecx")  # => eax
24919       3d/compare-eax-and 0/imm32/false
24920       75/break-if-!= break/disp8
24921       (emit-indent *(ebp+8) *Curr-block-depth)
24922       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
24923     }
24924     {
24925       (string-equal? %edx "eax")  # => eax
24926       3d/compare-eax-and 0/imm32/false
24927       75/break-if-!= break/disp8
24928       (emit-indent *(ebp+8) *Curr-block-depth)
24929       (write-buffered *(ebp+8) "58/pop-to-eax\n")
24930     }
24931 $translate-mu-length-stmt:end:
24932     # . restore registers
24933     5e/pop-to-esi
24934     5b/pop-to-ebx
24935     5a/pop-to-edx
24936     59/pop-to-ecx
24937     58/pop-to-eax
24938     # . epilogue
24939     89/<- %esp 5/r32/ebp
24940     5d/pop-to-ebp
24941     c3/return
24942 
24943 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
24944     # . prologue
24945     55/push-ebp
24946     89/<- %ebp 4/r32/esp
24947     #
24948     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
24949     (size-of-type-id-as-array-element %eax)  # => eax
24950 $array-element-size:end:
24951     # . epilogue
24952     89/<- %esp 5/r32/ebp
24953     5d/pop-to-ebp
24954     c3/return
24955 
24956 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
24957     # precondition: n is positive
24958     # . prologue
24959     55/push-ebp
24960     89/<- %ebp 4/r32/esp
24961     #
24962     8b/-> *(ebp+8) 0/r32/eax
24963     # var t/eax: (addr type-tree)
24964     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24965     # if t == 0 abort
24966     3d/compare-eax-with 0/imm32
24967     0f 84/jump-if-== $array-element-type-id:error0/disp32
24968     # if t->is-atom? abort
24969     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24970     0f 85/jump-if-!= $array-element-type-id:error1/disp32
24971     # if (t->left == addr) t = t->right
24972     {
24973       50/push-eax
24974       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24975       (is-simple-mu-type? %eax 2)  # addr => eax
24976       3d/compare-eax-with 0/imm32/false
24977       58/pop-to-eax
24978       74/jump-if-= break/disp8
24979 $array-element-type-id:skip-addr:
24980       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
24981     }
24982     # if t == 0 abort
24983     3d/compare-eax-with 0/imm32
24984     0f 84/jump-if-= $array-element-type-id:error2/disp32
24985     # if t->is-atom? abort
24986     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24987     0f 85/jump-if-!= $array-element-type-id:error2/disp32
24988     # if t->left != array abort
24989     {
24990       50/push-eax
24991       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24992       (is-simple-mu-type? %eax 3)  # array => eax
24993       3d/compare-eax-with 0/imm32/false
24994       58/pop-to-eax
24995 $array-element-type-id:no-array:
24996       0f 84/jump-if-= $array-element-type-id:error2/disp32
24997     }
24998 $array-element-type-id:skip-array:
24999     # t = t->right
25000     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25001     # if t == 0 abort
25002     3d/compare-eax-with 0/imm32
25003     0f 84/jump-if-= $array-element-type-id:error2/disp32
25004     # if t->is-atom? abort
25005     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25006     0f 85/jump-if-!= $array-element-type-id:error2/disp32
25007     # t = t->left
25008     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25009     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
25010     # if (t->is-atom == false) t = lookup(t->left)
25011     {
25012       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25013       75/jump-if-!= break/disp8
25014       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25015     }
25016     # return t->value
25017     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
25018 $array-element-type-id:end:
25019     # . epilogue
25020     89/<- %esp 5/r32/ebp
25021     5d/pop-to-ebp
25022     c3/return
25023 
25024 $array-element-type-id:error0:
25025     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
25026     50/push-eax
25027     8b/-> *(ebp+8) 0/r32/eax
25028     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25029     (write-buffered *(ebp+0xc) %eax)
25030     58/pop-to-eax
25031     (write-buffered *(ebp+0xc) "' has no type\n")
25032     (flush *(ebp+0xc))
25033     (stop *(ebp+0x10) 1)
25034     # never gets here
25035 
25036 $array-element-type-id:error1:
25037     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
25038     50/push-eax
25039     8b/-> *(ebp+8) 0/r32/eax
25040     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25041     (write-buffered *(ebp+0xc) %eax)
25042     58/pop-to-eax
25043     (write-buffered *(ebp+0xc) "' has atomic type ")
25044     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
25045     (write-buffered *(ebp+0xc) Newline)
25046     (flush *(ebp+0xc))
25047     (stop *(ebp+0x10) 1)
25048     # never gets here
25049 
25050 $array-element-type-id:error2:
25051     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
25052     50/push-eax
25053     8b/-> *(ebp+8) 0/r32/eax
25054     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25055     (write-buffered *(ebp+0xc) %eax)
25056     58/pop-to-eax
25057     (write-buffered *(ebp+0xc) "' has non-array type\n")
25058     (flush *(ebp+0xc))
25059     (stop *(ebp+0x10) 1)
25060     # never gets here
25061 
25062 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
25063     # . prologue
25064     55/push-ebp
25065     89/<- %ebp 4/r32/esp
25066     # eax = t
25067     8b/-> *(ebp+8) 0/r32/eax
25068     # if t is 'byte', size is 1
25069     3d/compare-eax-and 8/imm32/byte
25070     {
25071       75/jump-if-!= break/disp8
25072       b8/copy-to-eax 1/imm32
25073       eb/jump $size-of-type-id-as-array-element:end/disp8
25074     }
25075     # otherwise proceed as usual
25076     (size-of-type-id %eax)  # => eax
25077 $size-of-type-id-as-array-element:end:
25078     # . epilogue
25079     89/<- %esp 5/r32/ebp
25080     5d/pop-to-ebp
25081     c3/return
25082 
25083 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
25084     # . prologue
25085     55/push-ebp
25086     89/<- %ebp 4/r32/esp
25087     # . save registers
25088     50/push-eax
25089     53/push-ebx
25090     # ebx = base
25091     8b/-> *(ebp+0xc) 3/r32/ebx
25092     (emit-indent *(ebp+8) *Curr-block-depth)
25093     (write-buffered *(ebp+8) "8b/-> *")
25094     # if base is an (addr array ...) in a register
25095     {
25096       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
25097       74/jump-if-= break/disp8
25098 $emit-save-size-to:emit-base-from-register:
25099       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25100       (write-buffered *(ebp+8) %eax)
25101       eb/jump $emit-save-size-to:emit-output/disp8
25102     }
25103     # otherwise if base is an (array ...) on the stack
25104     {
25105       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
25106       74/jump-if-= break/disp8
25107 $emit-save-size-to:emit-base-from-stack:
25108       (write-buffered *(ebp+8) "(ebp+")
25109       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
25110       (write-buffered *(ebp+8) ")")
25111     }
25112 $emit-save-size-to:emit-output:
25113     (write-buffered *(ebp+8) " ")
25114     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
25115     (write-int32-hex-buffered *(ebp+8) *eax)
25116     (write-buffered *(ebp+8) "/r32\n")
25117 $emit-save-size-to:end:
25118     # . restore registers
25119     5b/pop-to-ebx
25120     58/pop-to-eax
25121     # . epilogue
25122     89/<- %esp 5/r32/ebp
25123     5d/pop-to-ebp
25124     c3/return
25125 
25126 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
25127     # . prologue
25128     55/push-ebp
25129     89/<- %ebp 4/r32/esp
25130     # . save registers
25131     50/push-eax
25132     #
25133     (emit-indent *(ebp+8) *Curr-block-depth)
25134     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
25135     (write-buffered *(ebp+8) *(ebp+0xc))
25136     (write-buffered *(ebp+8) Space)
25137     (num-shift-rights *(ebp+0x10))  # => eax
25138     (write-int32-hex-buffered *(ebp+8) %eax)
25139     (write-buffered *(ebp+8) "/imm8\n")
25140 $emit-divide-by-shift-right:end:
25141     # . restore registers
25142     58/pop-to-eax
25143     # . epilogue
25144     89/<- %esp 5/r32/ebp
25145     5d/pop-to-ebp
25146     c3/return
25147 
25148 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25149     # . prologue
25150     55/push-ebp
25151     89/<- %ebp 4/r32/esp
25152     # . save registers
25153     51/push-ecx
25154     # ecx = stmt
25155     8b/-> *(ebp+0xc) 1/r32/ecx
25156     # var base/ecx: (addr var) = stmt->inouts[0]
25157     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25158     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25159     89/<- %ecx 0/r32/eax
25160     # if (var->register) do one thing
25161     {
25162       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
25163       74/jump-if-= break/disp8
25164       # TODO: ensure there's no dereference
25165       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
25166       eb/jump $translate-mu-index-stmt:end/disp8
25167     }
25168     # if (var->offset) do a different thing
25169     {
25170       81 7/subop/compare *(ecx+0x14) 0/imm32  # Var-offset
25171       74/jump-if-= break/disp8
25172       # TODO: ensure there's no dereference
25173       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
25174       eb/jump $translate-mu-index-stmt:end/disp8
25175     }
25176 $translate-mu-index-stmt:end:
25177     # . restore registers
25178     59/pop-to-ecx
25179     # . epilogue
25180     89/<- %esp 5/r32/ebp
25181     5d/pop-to-ebp
25182     c3/return
25183 
25184 $translate-mu-index-stmt-with-array:error1:
25185     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
25186     (flush *(ebp+0x10))
25187     (stop *(ebp+0x14) 1)
25188     # never gets here
25189 
25190 $translate-mu-index-stmt-with-array:error2:
25191     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
25192     (flush *(ebp+0x10))
25193     (stop *(ebp+0x14) 1)
25194     # never gets here
25195 
25196 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25197     # . prologue
25198     55/push-ebp
25199     89/<- %ebp 4/r32/esp
25200     # . save registers
25201     50/push-eax
25202     51/push-ecx
25203     52/push-edx
25204     53/push-ebx
25205     #
25206     (emit-indent *(ebp+8) *Curr-block-depth)
25207     (write-buffered *(ebp+8) "8d/copy-address *(")
25208     # TODO: ensure inouts[0] is in a register and not dereferenced
25209 $translate-mu-index-stmt-with-array-in-register:emit-base:
25210     # ecx = stmt
25211     8b/-> *(ebp+0xc) 1/r32/ecx
25212     # var base/ebx: (addr var) = inouts[0]
25213     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25214     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25215     89/<- %ebx 0/r32/eax
25216     # print base->register " + "
25217     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25218     (write-buffered *(ebp+8) %eax)
25219     (write-buffered *(ebp+8) " + ")
25220     # var index/edx: (addr var) = inouts[1]
25221     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25222     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25223     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25224     89/<- %edx 0/r32/eax
25225     # if index->register
25226     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
25227     {
25228       0f 84/jump-if-= break/disp32
25229 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
25230       # if index is an int
25231       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25232       (is-simple-mu-type? %eax 1)  # int => eax
25233       3d/compare-eax-and 0/imm32/false
25234       {
25235         0f 84/jump-if-= break/disp32
25236 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
25237         # print index->register "<<" log2(array-element-size(base)) " + 4) "
25238         # . index->register "<<"
25239         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
25240         (write-buffered *(ebp+8) %eax)
25241         (write-buffered *(ebp+8) "<<")
25242         # . log2(array-element-size(base->type))
25243         # TODO: ensure size is a power of 2
25244         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
25245         (num-shift-rights %eax)  # => eax
25246         (write-int32-hex-buffered *(ebp+8) %eax)
25247         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
25248       }
25249       # if index->type is any other atom, abort
25250       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25251       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25252       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
25253       # if index has type (offset ...)
25254       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25255       (is-simple-mu-type? %eax 7)  # => eax
25256       3d/compare-eax-and 0/imm32/false
25257       {
25258         0f 84/jump-if-= break/disp32
25259         # print index->register
25260 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
25261         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
25262         (write-buffered *(ebp+8) %eax)
25263       }
25264 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
25265       (write-buffered *(ebp+8) " + 4) ")
25266       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
25267     }
25268     # otherwise if index is a literal
25269     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25270     (is-simple-mu-type? %eax 0)  # => eax
25271     3d/compare-eax-and 0/imm32/false
25272     {
25273       0f 84/jump-if-= break/disp32
25274 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
25275       # var index-value/edx: int = parse-hex-int(index->name)
25276       (lookup *edx *(edx+4))  # Var-name Var-name => eax
25277       (parse-hex-int %eax)  # => eax
25278       89/<- %edx 0/r32/eax
25279       # offset = idx-value * array-element-size(base->type)
25280       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
25281       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
25282       # offset += 4 for array size
25283       05/add-to-eax 4/imm32
25284       # TODO: check edx for overflow
25285       # print offset
25286       (write-int32-hex-buffered *(ebp+8) %eax)
25287       (write-buffered *(ebp+8) ") ")
25288       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
25289     }
25290     # otherwise abort
25291     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
25292 $translate-mu-index-stmt-with-array-in-register:emit-output:
25293     # outputs[0] "/r32"
25294     8b/-> *(ebp+0xc) 1/r32/ecx
25295     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25296     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25297     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25298     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
25299     (write-int32-hex-buffered *(ebp+8) *eax)
25300     (write-buffered *(ebp+8) "/r32\n")
25301 $translate-mu-index-stmt-with-array-in-register:end:
25302     # . restore registers
25303     5b/pop-to-ebx
25304     5a/pop-to-edx
25305     59/pop-to-ecx
25306     58/pop-to-eax
25307     # . epilogue
25308     89/<- %esp 5/r32/ebp
25309     5d/pop-to-ebp
25310     c3/return
25311 
25312 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25313     # . prologue
25314     55/push-ebp
25315     89/<- %ebp 4/r32/esp
25316     # . save registers
25317     50/push-eax
25318     51/push-ecx
25319     52/push-edx
25320     53/push-ebx
25321     #
25322     (emit-indent *(ebp+8) *Curr-block-depth)
25323     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
25324     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
25325     8b/-> *(ebp+0xc) 0/r32/eax
25326     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25327     89/<- %edx 0/r32/eax
25328     # var base/ecx: (addr var) = lookup(curr->value)
25329     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25330     89/<- %ecx 0/r32/eax
25331     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
25332     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
25333     # var index/edx: (handle var) = curr2->value
25334     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25335     89/<- %edx 0/r32/eax
25336     # if index->register
25337     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
25338     {
25339       0f 84/jump-if-= break/disp32
25340 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
25341       # if index is an int
25342       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25343       (is-simple-mu-type? %eax 1)  # int => eax
25344       3d/compare-eax-and 0/imm32/false
25345       {
25346         0f 84/jump-if-= break/disp32
25347 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
25348         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
25349         # . inouts[1]->register "<<"
25350         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
25351         (write-buffered *(ebp+8) %eax)
25352         (write-buffered *(ebp+8) "<<")
25353         # . log2(array-element-size(base))
25354         # TODO: ensure size is a power of 2
25355         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
25356         (num-shift-rights %eax)  # => eax
25357         (write-int32-hex-buffered *(ebp+8) %eax)
25358         #
25359         (write-buffered *(ebp+8) " + ")
25360         #
25361         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
25362         05/add-to-eax 4/imm32  # for array length
25363         (write-int32-hex-buffered *(ebp+8) %eax)
25364         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
25365       }
25366       # if index->type is any other atom, abort
25367       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25368       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25369       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
25370       # if index has type (offset ...)
25371       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25372       (is-simple-mu-type? %eax 7)  # => eax
25373       3d/compare-eax-and 0/imm32/false
25374       {
25375         0f 84/jump-if-= break/disp32
25376         # print index->register
25377 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
25378         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
25379         (write-buffered *(ebp+8) %eax)
25380       }
25381 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
25382       (write-buffered *(ebp+8) ") ")
25383       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
25384     }
25385     # otherwise if index is a literal
25386     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25387     (is-simple-mu-type? %eax 0)  # => eax
25388     3d/compare-eax-and 0/imm32/false
25389     {
25390       0f 84/jump-if-= break/disp32
25391 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
25392       # var idx-value/edx: int = parse-hex-int(index->name)
25393       (lookup *edx *(edx+4))  # Var-name Var-name => eax
25394       (parse-hex-int %eax)  # Var-name => eax
25395       89/<- %edx 0/r32/eax
25396       # offset = idx-value * array-element-size(base)
25397       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
25398       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
25399       # offset += base->offset
25400       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
25401       # offset += 4 for array size
25402       05/add-to-eax 4/imm32
25403       # TODO: check edx for overflow
25404       # print offset
25405       (write-int32-hex-buffered *(ebp+8) %eax)
25406       (write-buffered *(ebp+8) ") ")
25407       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
25408     }
25409     # otherwise abort
25410     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
25411 $translate-mu-index-stmt-with-array-on-stack:emit-output:
25412     # outputs[0] "/r32"
25413     8b/-> *(ebp+0xc) 0/r32/eax
25414     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25415     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25416     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25417     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
25418     (write-int32-hex-buffered *(ebp+8) *eax)
25419     (write-buffered *(ebp+8) "/r32\n")
25420 $translate-mu-index-stmt-with-array-on-stack:end:
25421     # . restore registers
25422     5b/pop-to-ebx
25423     5a/pop-to-edx
25424     59/pop-to-ecx
25425     58/pop-to-eax
25426     # . epilogue
25427     89/<- %esp 5/r32/ebp
25428     5d/pop-to-ebp
25429     c3/return
25430 
25431 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25432     # . prologue
25433     55/push-ebp
25434     89/<- %ebp 4/r32/esp
25435     # . save registers
25436     50/push-eax
25437     51/push-ecx
25438     52/push-edx
25439     53/push-ebx
25440     #
25441     (emit-indent *(ebp+8) *Curr-block-depth)
25442     (write-buffered *(ebp+8) "69/multiply")
25443     # ecx = stmt
25444     8b/-> *(ebp+0xc) 1/r32/ecx
25445     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
25446     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25447     89/<- %ebx 0/r32/eax
25448 $translate-mu-compute-index-stmt:emit-index:
25449     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
25450     (emit-subx-var-as-rm32 *(ebp+8) %eax)
25451     (write-buffered *(ebp+8) Space)
25452 $translate-mu-compute-index-stmt:emit-elem-size:
25453     # var base/ebx: (addr var)
25454     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
25455     89/<- %ebx 0/r32/eax
25456     # print array-element-size(base)
25457     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
25458     (write-int32-hex-buffered *(ebp+8) %eax)
25459     (write-buffered *(ebp+8) "/imm32 ")
25460 $translate-mu-compute-index-stmt:emit-output:
25461     # outputs[0] "/r32"
25462     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25463     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25464     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25465     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
25466     (write-int32-hex-buffered *(ebp+8) *eax)
25467     (write-buffered *(ebp+8) "/r32\n")
25468 $translate-mu-compute-index-stmt:end:
25469     # . restore registers
25470     5b/pop-to-ebx
25471     5a/pop-to-edx
25472     59/pop-to-ecx
25473     58/pop-to-eax
25474     # . epilogue
25475     89/<- %esp 5/r32/ebp
25476     5d/pop-to-ebp
25477     c3/return
25478 
25479 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
25480     # . prologue
25481     55/push-ebp
25482     89/<- %ebp 4/r32/esp
25483     # . save registers
25484     50/push-eax
25485     51/push-ecx
25486     52/push-edx
25487     #
25488     (emit-indent *(ebp+8) *Curr-block-depth)
25489     (write-buffered *(ebp+8) "8d/copy-address ")
25490     # ecx = stmt
25491     8b/-> *(ebp+0xc) 1/r32/ecx
25492     # var offset/edx: int = get offset of stmt
25493     (mu-get-offset %ecx)  # => eax
25494     89/<- %edx 0/r32/eax
25495     # var base/eax: (addr var) = stmt->inouts->value
25496     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25497     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25498     # if base is in a register
25499     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
25500     {
25501       0f 84/jump-if-= break/disp32
25502 $translate-mu-get-stmt:emit-register-input:
25503       # emit "*(" base->register " + " offset ") "
25504       (write-buffered *(ebp+8) "*(")
25505       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25506       (write-buffered *(ebp+8) %eax)
25507       (write-buffered *(ebp+8) " + ")
25508       (write-int32-hex-buffered *(ebp+8) %edx)
25509       (write-buffered *(ebp+8) ") ")
25510       e9/jump $translate-mu-get-stmt:emit-output/disp32
25511     }
25512     # otherwise base is on the stack
25513     {
25514 $translate-mu-get-stmt:emit-stack-input:
25515       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
25516       (write-buffered *(ebp+8) "*(ebp+")
25517       03/add *(eax+0x14) 2/r32/edx  # Var-offset
25518       (write-int32-hex-buffered *(ebp+8) %edx)
25519       (write-buffered *(ebp+8) ") ")
25520       eb/jump $translate-mu-get-stmt:emit-output/disp8
25521     }
25522 $translate-mu-get-stmt:emit-output:
25523     # var output/eax: (addr var) = stmt->outputs->value
25524     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25525     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25526     # emit offset->register "/r32"
25527     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25528     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
25529     (write-int32-hex-buffered *(ebp+8) *eax)
25530     (write-buffered *(ebp+8) "/r32\n")
25531 $translate-mu-get-stmt:end:
25532     # . restore registers
25533     5a/pop-to-edx
25534     59/pop-to-ecx
25535     58/pop-to-eax
25536     # . epilogue
25537     89/<- %esp 5/r32/ebp
25538     5d/pop-to-ebp
25539     c3/return
25540 
25541 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25542     # . prologue
25543     55/push-ebp
25544     89/<- %ebp 4/r32/esp
25545     # . save registers
25546     50/push-eax
25547     #
25548     (emit-indent *(ebp+8) *Curr-block-depth)
25549     (write-buffered *(ebp+8) "(copy-bytes")
25550     # eax = stmt
25551     8b/-> *(ebp+0xc) 0/r32/eax
25552     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
25553     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25554     (emit-subx-call-operand *(ebp+8) %eax)
25555     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25556     (emit-subx-call-operand *(ebp+8) %eax)
25557     (write-buffered *(ebp+8) Space)
25558     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
25559     (write-int32-hex-buffered *(ebp+8) %eax)
25560     (write-buffered *(ebp+8) ")\n")
25561 $translate-mu-copy-object-stmt:end:
25562     # . restore registers
25563     58/pop-to-eax
25564     # . epilogue
25565     89/<- %esp 5/r32/ebp
25566     5d/pop-to-ebp
25567     c3/return
25568 
25569 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25570     # . prologue
25571     55/push-ebp
25572     89/<- %ebp 4/r32/esp
25573     # . save registers
25574     50/push-eax
25575     56/push-esi
25576     57/push-edi
25577     # esi = stmt
25578     8b/-> *(ebp+0xc) 6/r32/esi
25579     # var target/edi: (addr stmt-var) = stmt->inouts[0]
25580     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25581     89/<- %edi 0/r32/eax
25582     #
25583     (emit-indent *(ebp+8) *Curr-block-depth)
25584     (write-buffered *(ebp+8) "(allocate Heap ")
25585     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
25586     (write-int32-hex-buffered *(ebp+8) %eax)
25587     (emit-subx-call-operand *(ebp+8) %edi)
25588     (write-buffered *(ebp+8) ")\n")
25589 $translate-mu-allocate-stmt:end:
25590     # . restore registers
25591     5f/pop-to-edi
25592     5e/pop-to-esi
25593     58/pop-to-eax
25594     # . epilogue
25595     89/<- %esp 5/r32/ebp
25596     5d/pop-to-ebp
25597     c3/return
25598 
25599 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
25600     # . prologue
25601     55/push-ebp
25602     89/<- %ebp 4/r32/esp
25603     # var t/eax: (addr type-tree) = s->value->type
25604     8b/-> *(ebp+8) 0/r32/eax
25605     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25606     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25607     # TODO: check eax != 0
25608     # TODO: check !t->is-atom?
25609     # TODO: check t->left == addr
25610     # t = t->right
25611 $addr-handle-payload-size:skip-addr:
25612     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25613     # TODO: check eax != 0
25614     # TODO: check !t->is-atom?
25615     # TODO: check t->left == handle
25616     # t = t->right
25617 $addr-handle-payload-size:skip-handle:
25618     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25619     # TODO: check eax != 0
25620     # if !t->is-atom? t = t->left
25621     81 7/subop/compare *eax 0/imm32/false
25622     {
25623       75/jump-if-!= break/disp8
25624       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25625     }
25626     # TODO: check t->is-atom?
25627     # return size(t->value)
25628     (size-of-type-id *(eax+4))  # Type-tree-value => eax
25629 $addr-handle-payload-size:end:
25630     # . epilogue
25631     89/<- %esp 5/r32/ebp
25632     5d/pop-to-ebp
25633     c3/return
25634 
25635 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
25636     # . prologue
25637     55/push-ebp
25638     89/<- %ebp 4/r32/esp
25639     # var t/eax: (addr type-tree) = s->value->type
25640     8b/-> *(ebp+8) 0/r32/eax
25641     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25642     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25643     # TODO: check eax != 0
25644     # TODO: check !t->is-atom?
25645     # TODO: check t->left == addr
25646     # t = t->right
25647 $addr-payload-size:skip-addr:
25648     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25649     # TODO: check eax != 0
25650     # if !t->is-atom? t = t->left
25651     81 7/subop/compare *eax 0/imm32/false
25652     {
25653       75/jump-if-!= break/disp8
25654       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25655     }
25656     # TODO: check t->is-atom?
25657     # return size(t->value)
25658     (size-of-type-id *(eax+4))  # Type-tree-value => eax
25659 $addr-payload-size:end:
25660     # . epilogue
25661     89/<- %esp 5/r32/ebp
25662     5d/pop-to-ebp
25663     c3/return
25664 
25665 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25666     # . prologue
25667     55/push-ebp
25668     89/<- %ebp 4/r32/esp
25669     # . save registers
25670     50/push-eax
25671     51/push-ecx
25672     56/push-esi
25673     57/push-edi
25674     # esi = stmt
25675     8b/-> *(ebp+0xc) 6/r32/esi
25676     # var target/edi: (addr stmt-var) = stmt->inouts[0]
25677     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25678     89/<- %edi 0/r32/eax
25679     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
25680     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25681     89/<- %ecx 0/r32/eax
25682     #
25683     (emit-indent *(ebp+8) *Curr-block-depth)
25684     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
25685     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
25686     (write-int32-hex-buffered *(ebp+8) %eax)
25687     (emit-subx-call-operand *(ebp+8) %ecx)
25688     (emit-subx-call-operand *(ebp+8) %edi)
25689     (write-buffered *(ebp+8) ")\n")
25690 $translate-mu-populate-stmt:end:
25691     # . restore registers
25692     5f/pop-to-edi
25693     5e/pop-to-esi
25694     59/pop-to-ecx
25695     58/pop-to-eax
25696     # . epilogue
25697     89/<- %esp 5/r32/ebp
25698     5d/pop-to-ebp
25699     c3/return
25700 
25701 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25702     # . prologue
25703     55/push-ebp
25704     89/<- %ebp 4/r32/esp
25705     # . save registers
25706     50/push-eax
25707     51/push-ecx
25708     56/push-esi
25709     57/push-edi
25710     # esi = stmt
25711     8b/-> *(ebp+0xc) 6/r32/esi
25712     # var target/edi: (addr stmt-var) = stmt->inouts[0]
25713     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25714     89/<- %edi 0/r32/eax
25715     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
25716     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25717     89/<- %ecx 0/r32/eax
25718     #
25719     (emit-indent *(ebp+8) *Curr-block-depth)
25720     (write-buffered *(ebp+8) "(new-stream Heap ")
25721     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
25722     (write-int32-hex-buffered *(ebp+8) %eax)
25723     (emit-subx-call-operand *(ebp+8) %ecx)
25724     (emit-subx-call-operand *(ebp+8) %edi)
25725     (write-buffered *(ebp+8) ")\n")
25726 $translate-mu-populate-stream-stmt:end:
25727     # . restore registers
25728     5f/pop-to-edi
25729     5e/pop-to-esi
25730     59/pop-to-ecx
25731     58/pop-to-eax
25732     # . epilogue
25733     89/<- %esp 5/r32/ebp
25734     5d/pop-to-ebp
25735     c3/return
25736 
25737 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25738     # . prologue
25739     55/push-ebp
25740     89/<- %ebp 4/r32/esp
25741     # . save registers
25742     50/push-eax
25743     51/push-ecx
25744     56/push-esi
25745     57/push-edi
25746     # esi = stmt
25747     8b/-> *(ebp+0xc) 6/r32/esi
25748     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
25749     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25750     89/<- %ecx 0/r32/eax
25751     # var target/edi: (addr stmt-var) = stmt->inouts[1]
25752     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
25753     89/<- %edi 0/r32/eax
25754     #
25755     (emit-indent *(ebp+8) *Curr-block-depth)
25756     (write-buffered *(ebp+8) "(read-from-stream")
25757     (emit-subx-call-operand *(ebp+8) %ecx)
25758     (emit-subx-call-operand *(ebp+8) %edi)
25759     (write-buffered *(ebp+8) Space)
25760     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
25761     (write-int32-hex-buffered *(ebp+8) %eax)
25762     (write-buffered *(ebp+8) ")\n")
25763 $translate-mu-read-from-stream-stmt:end:
25764     # . restore registers
25765     5f/pop-to-edi
25766     5e/pop-to-esi
25767     59/pop-to-ecx
25768     58/pop-to-eax
25769     # . epilogue
25770     89/<- %esp 5/r32/ebp
25771     5d/pop-to-ebp
25772     c3/return
25773 
25774 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25775     # . prologue
25776     55/push-ebp
25777     89/<- %ebp 4/r32/esp
25778     # . save registers
25779     50/push-eax
25780     51/push-ecx
25781     56/push-esi
25782     57/push-edi
25783     # esi = stmt
25784     8b/-> *(ebp+0xc) 6/r32/esi
25785     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
25786     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25787     89/<- %ecx 0/r32/eax
25788     # var target/edi: (addr stmt-var) = stmt->inouts[1]
25789     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
25790     89/<- %edi 0/r32/eax
25791     #
25792     (emit-indent *(ebp+8) *Curr-block-depth)
25793     (write-buffered *(ebp+8) "(write-to-stream")
25794     (emit-subx-call-operand *(ebp+8) %ecx)
25795     (flush *(ebp+8))
25796     (emit-subx-call-operand *(ebp+8) %edi)
25797     (flush *(ebp+8))
25798     (write-buffered *(ebp+8) Space)
25799     (flush *(ebp+8))
25800     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
25801     (write-int32-hex-buffered *(ebp+8) %eax)
25802     (write-buffered *(ebp+8) ")\n")
25803 $translate-mu-write-to-stream-stmt:end:
25804     # . restore registers
25805     5f/pop-to-edi
25806     5e/pop-to-esi
25807     59/pop-to-ecx
25808     58/pop-to-eax
25809     # . epilogue
25810     89/<- %esp 5/r32/ebp
25811     5d/pop-to-ebp
25812     c3/return
25813 
25814 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
25815     # . prologue
25816     55/push-ebp
25817     89/<- %ebp 4/r32/esp
25818     # var t/eax: (addr type-tree) = s->value->type
25819     8b/-> *(ebp+8) 0/r32/eax
25820     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25821     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25822     # TODO: check eax != 0
25823     # TODO: check !t->is-atom?
25824     # TODO: check t->left == addr
25825     # t = t->right
25826 $addr-handle-array-payload-size:skip-addr:
25827     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25828     # TODO: check eax != 0
25829     # TODO: check !t->is-atom?
25830     # TODO: check t->left == handle
25831     # t = t->right
25832 $addr-handle-array-payload-size:skip-handle:
25833     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25834     # TODO: check eax != 0
25835     # TODO: check !t->is-atom?
25836     # TODO: check t->left == array
25837     # t = t->right
25838 $addr-handle-array-payload-size:skip-array:
25839     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25840     # TODO: check eax != 0
25841     # if !t->is-atom? t = t->left
25842     81 7/subop/compare *eax 0/imm32/false
25843     {
25844       75/jump-if-!= break/disp8
25845       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25846     }
25847 $addr-handle-array-payload-size:compute-size:
25848     # TODO: check t->is-atom?
25849     # return size(t->value)
25850     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
25851 $addr-handle-array-payload-size:end:
25852     # . epilogue
25853     89/<- %esp 5/r32/ebp
25854     5d/pop-to-ebp
25855     c3/return
25856 
25857 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
25858     # . prologue
25859     55/push-ebp
25860     89/<- %ebp 4/r32/esp
25861     # var t/eax: (addr type-tree) = s->value->type
25862     8b/-> *(ebp+8) 0/r32/eax
25863     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25864     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25865     # TODO: check eax != 0
25866     # TODO: check !t->is-atom?
25867     # TODO: check t->left == addr
25868     # t = t->right
25869 $addr-handle-stream-payload-size:skip-addr:
25870     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25871     # TODO: check eax != 0
25872     # TODO: check !t->is-atom?
25873     # TODO: check t->left == handle
25874     # t = t->right
25875 $addr-handle-stream-payload-size:skip-handle:
25876     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25877     # TODO: check eax != 0
25878     # TODO: check !t->is-atom?
25879     # TODO: check t->left == stream
25880     # t = t->right
25881 $addr-handle-stream-payload-size:skip-stream:
25882     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25883     # TODO: check eax != 0
25884     # if !t->is-atom? t = t->left
25885     81 7/subop/compare *eax 0/imm32/false
25886     {
25887       75/jump-if-!= break/disp8
25888       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25889     }
25890 $addr-handle-stream-payload-size:compute-size:
25891     # TODO: check t->is-atom?
25892     # return size(t->value)
25893     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
25894 $addr-handle-stream-payload-size:end:
25895     # . epilogue
25896     89/<- %esp 5/r32/ebp
25897     5d/pop-to-ebp
25898     c3/return
25899 
25900 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
25901     # precondition: n is positive
25902     # . prologue
25903     55/push-ebp
25904     89/<- %ebp 4/r32/esp
25905     # eax = n
25906     8b/-> *(ebp+8) 0/r32/eax
25907     # if (n < 0) abort
25908     3d/compare-eax-with 0/imm32
25909     0f 8c/jump-if-< $power-of-2?:abort/disp32
25910     # var tmp/eax: int = n-1
25911     48/decrement-eax
25912     # var tmp2/eax: int = n & tmp
25913     23/and-> *(ebp+8) 0/r32/eax
25914     # return (tmp2 == 0)
25915     3d/compare-eax-and 0/imm32
25916     0f 94/set-byte-if-= %al
25917     81 4/subop/and %eax 0xff/imm32
25918 $power-of-2?:end:
25919     # . epilogue
25920     89/<- %esp 5/r32/ebp
25921     5d/pop-to-ebp
25922     c3/return
25923 
25924 $power-of-2?:abort:
25925     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
25926     (flush *(ebp+0xc))
25927     (stop *(ebp+0x10) 1)
25928     # never gets here
25929 
25930 num-shift-rights:  # n: int -> result/eax: int
25931     # precondition: n is a positive power of 2
25932     # . prologue
25933     55/push-ebp
25934     89/<- %ebp 4/r32/esp
25935     # . save registers
25936     51/push-ecx
25937     # var curr/ecx: int = n
25938     8b/-> *(ebp+8) 1/r32/ecx
25939     # result = 0
25940     b8/copy-to-eax 0/imm32
25941     {
25942       # if (curr <= 1) break
25943       81 7/subop/compare %ecx 1/imm32
25944       7e/jump-if-<= break/disp8
25945       40/increment-eax
25946       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
25947       eb/jump loop/disp8
25948     }
25949 $num-shift-rights:end:
25950     # . restore registers
25951     59/pop-to-ecx
25952     # . epilogue
25953     89/<- %esp 5/r32/ebp
25954     5d/pop-to-ebp
25955     c3/return
25956 
25957 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
25958     # . prologue
25959     55/push-ebp
25960     89/<- %ebp 4/r32/esp
25961     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
25962     8b/-> *(ebp+8) 0/r32/eax
25963     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25964     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25965     # var output-var/eax: (addr var) = second-inout->value
25966     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25967 #?     (write-buffered Stderr "mu-get-offset: ")
25968 #?     (write-int32-hex-buffered Stderr %eax)
25969 #?     (write-buffered Stderr " name: ")
25970 #?     50/push-eax
25971 #?     (lookup *eax *(eax+4))  # Var-name
25972 #?     (write-buffered Stderr %eax)
25973 #?     58/pop-to-eax
25974 #?     (write-buffered Stderr Newline)
25975 #?     (flush Stderr)
25976     # return output-var->stack-offset
25977     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
25978 #?     (write-buffered Stderr "=> ")
25979 #?     (write-int32-hex-buffered Stderr %eax)
25980 #?     (write-buffered Stderr Newline)
25981 #?     (flush Stderr)
25982 $emit-get-offset:end:
25983     # . epilogue
25984     89/<- %esp 5/r32/ebp
25985     5d/pop-to-ebp
25986     c3/return
25987 
25988 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)
25989     # . prologue
25990     55/push-ebp
25991     89/<- %ebp 4/r32/esp
25992     # . save registers
25993     50/push-eax
25994     51/push-ecx
25995     56/push-esi
25996     # esi = block
25997     8b/-> *(ebp+0xc) 6/r32/esi
25998     # block->var->block-depth = *Curr-block-depth
25999     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
26000     8b/-> *Curr-block-depth 1/r32/ecx
26001     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
26002     # var stmts/eax: (addr list stmt) = lookup(block->statements)
26003     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
26004     #
26005     {
26006 $emit-subx-block:check-empty:
26007       3d/compare-eax-and 0/imm32
26008       0f 84/jump-if-= break/disp32
26009       (emit-indent *(ebp+8) *Curr-block-depth)
26010       (write-buffered *(ebp+8) "{\n")
26011       # var v/ecx: (addr var) = lookup(block->var)
26012       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
26013       89/<- %ecx 0/r32/eax
26014       #
26015       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
26016       (write-buffered *(ebp+8) %eax)
26017       (write-buffered *(ebp+8) ":loop:\n")
26018       ff 0/subop/increment *Curr-block-depth
26019       (push *(ebp+0x10) *(esi+0xc))  # Block-var
26020       (push *(ebp+0x10) *(esi+0x10))  # Block-var
26021       (push *(ebp+0x10) 0)  # false
26022       # emit block->statements
26023       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
26024       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
26025       (pop *(ebp+0x10))  # => eax
26026       (pop *(ebp+0x10))  # => eax
26027       (pop *(ebp+0x10))  # => eax
26028       ff 1/subop/decrement *Curr-block-depth
26029       (emit-indent *(ebp+8) *Curr-block-depth)
26030       (write-buffered *(ebp+8) "}\n")
26031       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
26032       (write-buffered *(ebp+8) %eax)
26033       (write-buffered *(ebp+8) ":break:\n")
26034     }
26035 $emit-subx-block:end:
26036     # . restore registers
26037     5e/pop-to-esi
26038     59/pop-to-ecx
26039     58/pop-to-eax
26040     # . epilogue
26041     89/<- %esp 5/r32/ebp
26042     5d/pop-to-ebp
26043     c3/return
26044 
26045 # Primitives supported
26046 # See mu_instructions for a summary of this linked-list data structure.
26047 #
26048 # For each operation, put variants with hard-coded registers before flexible ones.
26049 #
26050 # Unfortunately, our restrictions on addresses require that various fields in
26051 # primitives be handles, which complicates these definitions.
26052 #   - we need to insert dummy fields all over the place for fake alloc-ids
26053 #   - we can't use our syntax sugar of quoted literals for string fields
26054 #
26055 # Fake alloc-ids are needed because our type definitions up top require
26056 # handles but it's clearer to statically allocate these long-lived objects.
26057 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
26058 #
26059 # Every 'object' below starts with a fake alloc-id. It may also contain other
26060 # fake alloc-ids for various handle fields.
26061 #
26062 # I think of objects starting with a fake alloc-id as having type 'payload'.
26063 # It's not really intended to be created dynamically; for that use `allocate`
26064 # as usual.
26065 #
26066 # Idea for a notation to simplify such definitions:
26067 #   _Primitive-increment-eax:  # (payload primitive)
26068 #     0x11/alloc-id:fake:payload
26069 #     0x11 @(0x11 "increment")  # name
26070 #     0 0                       # inouts
26071 #     0x11 @(0x11/payload
26072 #            0x11 @(0x11/payload  # List-value
26073 #                   0 0             # Var-name
26074 #                   0x11 @(0x11     # Var-type
26075 #                          1/is-atom
26076 #                          1/value 0/unused   # Type-tree-left
26077 #                          0 0                # Type-tree-right
26078 #                         )
26079 #                   1               # block-depth
26080 #                   0               # stack-offset
26081 #                   0x11 @(0x11 "eax")  # Var-register
26082 #                  )
26083 #            0 0)                 # List-next
26084 #     ...
26085 #     _Primitive-increment-ecx/imm32/next
26086 #   ...
26087 # Awfully complex and non-obvious. But also clearly signals there's something
26088 # to learn here, so may be worth trying.
26089 #
26090 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
26091 #
26092 # For now we'll continue to just use comments and manually ensure they stay up
26093 # to date.
26094 == data
26095 Primitives:  # (addr primitive)
26096 # - increment/decrement
26097 _Primitive-increment-eax:  # (addr primitive)
26098     # var/eax <- increment => 40/increment-eax
26099     0x11/imm32/alloc-id:fake
26100     _string-increment/imm32/name
26101     0/imm32/no-inouts
26102     0/imm32/no-inouts
26103     0x11/imm32/alloc-id:fake
26104     Single-int-var-in-eax/imm32/outputs
26105     0x11/imm32/alloc-id:fake
26106     _string_40_increment_eax/imm32/subx-name
26107     0/imm32/no-rm32
26108     0/imm32/no-r32
26109     0/imm32/no-imm32
26110     0/imm32/no-imm8
26111     0/imm32/no-disp32
26112     0/imm32/no-xm32
26113     0/imm32/no-x32
26114     0x11/imm32/alloc-id:fake
26115     _Primitive-increment-ecx/imm32/next
26116 _Primitive-increment-ecx:  # (payload primitive)
26117     0x11/imm32/alloc-id:fake:payload
26118     # var/ecx <- increment => 41/increment-ecx
26119     0x11/imm32/alloc-id:fake
26120     _string-increment/imm32/name
26121     0/imm32/no-inouts
26122     0/imm32/no-inouts
26123     0x11/imm32/alloc-id:fake
26124     Single-int-var-in-ecx/imm32/outputs
26125     0x11/imm32/alloc-id:fake
26126     _string_41_increment_ecx/imm32/subx-name
26127     0/imm32/no-rm32
26128     0/imm32/no-r32
26129     0/imm32/no-imm32
26130     0/imm32/no-imm8
26131     0/imm32/no-disp32
26132     0/imm32/no-xm32
26133     0/imm32/no-x32
26134     0x11/imm32/alloc-id:fake
26135     _Primitive-increment-edx/imm32/next
26136 _Primitive-increment-edx:  # (payload primitive)
26137     0x11/imm32/alloc-id:fake:payload
26138     # var/edx <- increment => 42/increment-edx
26139     0x11/imm32/alloc-id:fake
26140     _string-increment/imm32/name
26141     0/imm32/no-inouts
26142     0/imm32/no-inouts
26143     0x11/imm32/alloc-id:fake
26144     Single-int-var-in-edx/imm32/outputs
26145     0x11/imm32/alloc-id:fake
26146     _string_42_increment_edx/imm32/subx-name
26147     0/imm32/no-rm32
26148     0/imm32/no-r32
26149     0/imm32/no-imm32
26150     0/imm32/no-imm8
26151     0/imm32/no-disp32
26152     0/imm32/no-xm32
26153     0/imm32/no-x32
26154     0x11/imm32/alloc-id:fake
26155     _Primitive-increment-ebx/imm32/next
26156 _Primitive-increment-ebx:  # (payload primitive)
26157     0x11/imm32/alloc-id:fake:payload
26158     # var/ebx <- increment => 43/increment-ebx
26159     0x11/imm32/alloc-id:fake
26160     _string-increment/imm32/name
26161     0/imm32/no-inouts
26162     0/imm32/no-inouts
26163     0x11/imm32/alloc-id:fake
26164     Single-int-var-in-ebx/imm32/outputs
26165     0x11/imm32/alloc-id:fake
26166     _string_43_increment_ebx/imm32/subx-name
26167     0/imm32/no-rm32
26168     0/imm32/no-r32
26169     0/imm32/no-imm32
26170     0/imm32/no-imm8
26171     0/imm32/no-disp32
26172     0/imm32/no-xm32
26173     0/imm32/no-x32
26174     0x11/imm32/alloc-id:fake
26175     _Primitive-increment-esi/imm32/next
26176 _Primitive-increment-esi:  # (payload primitive)
26177     0x11/imm32/alloc-id:fake:payload
26178     # var/esi <- increment => 46/increment-esi
26179     0x11/imm32/alloc-id:fake
26180     _string-increment/imm32/name
26181     0/imm32/no-inouts
26182     0/imm32/no-inouts
26183     0x11/imm32/alloc-id:fake
26184     Single-int-var-in-esi/imm32/outputs
26185     0x11/imm32/alloc-id:fake
26186     _string_46_increment_esi/imm32/subx-name
26187     0/imm32/no-rm32
26188     0/imm32/no-r32
26189     0/imm32/no-imm32
26190     0/imm32/no-imm8
26191     0/imm32/no-disp32
26192     0/imm32/no-xm32
26193     0/imm32/no-x32
26194     0x11/imm32/alloc-id:fake
26195     _Primitive-increment-edi/imm32/next
26196 _Primitive-increment-edi:  # (payload primitive)
26197     0x11/imm32/alloc-id:fake:payload
26198     # var/edi <- increment => 47/increment-edi
26199     0x11/imm32/alloc-id:fake
26200     _string-increment/imm32/name
26201     0/imm32/no-inouts
26202     0/imm32/no-inouts
26203     0x11/imm32/alloc-id:fake
26204     Single-int-var-in-edi/imm32/outputs
26205     0x11/imm32/alloc-id:fake
26206     _string_47_increment_edi/imm32/subx-name
26207     0/imm32/no-rm32
26208     0/imm32/no-r32
26209     0/imm32/no-imm32
26210     0/imm32/no-imm8
26211     0/imm32/no-disp32
26212     0/imm32/no-xm32
26213     0/imm32/no-x32
26214     0x11/imm32/alloc-id:fake
26215     _Primitive-decrement-eax/imm32/next
26216 _Primitive-decrement-eax:  # (payload primitive)
26217     0x11/imm32/alloc-id:fake:payload
26218     # var/eax <- decrement => 48/decrement-eax
26219     0x11/imm32/alloc-id:fake
26220     _string-decrement/imm32/name
26221     0/imm32/no-inouts
26222     0/imm32/no-inouts
26223     0x11/imm32/alloc-id:fake
26224     Single-int-var-in-eax/imm32/outputs
26225     0x11/imm32/alloc-id:fake
26226     _string_48_decrement_eax/imm32/subx-name
26227     0/imm32/no-rm32
26228     0/imm32/no-r32
26229     0/imm32/no-imm32
26230     0/imm32/no-imm8
26231     0/imm32/no-disp32
26232     0/imm32/no-xm32
26233     0/imm32/no-x32
26234     0x11/imm32/alloc-id:fake
26235     _Primitive-decrement-ecx/imm32/next
26236 _Primitive-decrement-ecx:  # (payload primitive)
26237     0x11/imm32/alloc-id:fake:payload
26238     # var/ecx <- decrement => 49/decrement-ecx
26239     0x11/imm32/alloc-id:fake
26240     _string-decrement/imm32/name
26241     0/imm32/no-inouts
26242     0/imm32/no-inouts
26243     0x11/imm32/alloc-id:fake
26244     Single-int-var-in-ecx/imm32/outputs
26245     0x11/imm32/alloc-id:fake
26246     _string_49_decrement_ecx/imm32/subx-name
26247     0/imm32/no-rm32
26248     0/imm32/no-r32
26249     0/imm32/no-imm32
26250     0/imm32/no-imm8
26251     0/imm32/no-disp32
26252     0/imm32/no-xm32
26253     0/imm32/no-x32
26254     0x11/imm32/alloc-id:fake
26255     _Primitive-decrement-edx/imm32/next
26256 _Primitive-decrement-edx:  # (payload primitive)
26257     0x11/imm32/alloc-id:fake:payload
26258     # var/edx <- decrement => 4a/decrement-edx
26259     0x11/imm32/alloc-id:fake
26260     _string-decrement/imm32/name
26261     0/imm32/no-inouts
26262     0/imm32/no-inouts
26263     0x11/imm32/alloc-id:fake
26264     Single-int-var-in-edx/imm32/outputs
26265     0x11/imm32/alloc-id:fake
26266     _string_4a_decrement_edx/imm32/subx-name
26267     0/imm32/no-rm32
26268     0/imm32/no-r32
26269     0/imm32/no-imm32
26270     0/imm32/no-imm8
26271     0/imm32/no-disp32
26272     0/imm32/no-xm32
26273     0/imm32/no-x32
26274     0x11/imm32/alloc-id:fake
26275     _Primitive-decrement-ebx/imm32/next
26276 _Primitive-decrement-ebx:  # (payload primitive)
26277     0x11/imm32/alloc-id:fake:payload
26278     # var/ebx <- decrement => 4b/decrement-ebx
26279     0x11/imm32/alloc-id:fake
26280     _string-decrement/imm32/name
26281     0/imm32/no-inouts
26282     0/imm32/no-inouts
26283     0x11/imm32/alloc-id:fake
26284     Single-int-var-in-ebx/imm32/outputs
26285     0x11/imm32/alloc-id:fake
26286     _string_4b_decrement_ebx/imm32/subx-name
26287     0/imm32/no-rm32
26288     0/imm32/no-r32
26289     0/imm32/no-imm32
26290     0/imm32/no-imm8
26291     0/imm32/no-disp32
26292     0/imm32/no-xm32
26293     0/imm32/no-x32
26294     0x11/imm32/alloc-id:fake
26295     _Primitive-decrement-esi/imm32/next
26296 _Primitive-decrement-esi:  # (payload primitive)
26297     0x11/imm32/alloc-id:fake:payload
26298     # var/esi <- decrement => 4e/decrement-esi
26299     0x11/imm32/alloc-id:fake
26300     _string-decrement/imm32/name
26301     0/imm32/no-inouts
26302     0/imm32/no-inouts
26303     0x11/imm32/alloc-id:fake
26304     Single-int-var-in-esi/imm32/outputs
26305     0x11/imm32/alloc-id:fake
26306     _string_4e_decrement_esi/imm32/subx-name
26307     0/imm32/no-rm32
26308     0/imm32/no-r32
26309     0/imm32/no-imm32
26310     0/imm32/no-imm8
26311     0/imm32/no-disp32
26312     0/imm32/no-xm32
26313     0/imm32/no-x32
26314     0x11/imm32/alloc-id:fake
26315     _Primitive-decrement-edi/imm32/next
26316 _Primitive-decrement-edi:  # (payload primitive)
26317     0x11/imm32/alloc-id:fake:payload
26318     # var/edi <- decrement => 4f/decrement-edi
26319     0x11/imm32/alloc-id:fake
26320     _string-decrement/imm32/name
26321     0/imm32/no-inouts
26322     0/imm32/no-inouts
26323     0x11/imm32/alloc-id:fake
26324     Single-int-var-in-edi/imm32/outputs
26325     0x11/imm32/alloc-id:fake
26326     _string_4f_decrement_edi/imm32/subx-name
26327     0/imm32/no-rm32
26328     0/imm32/no-r32
26329     0/imm32/no-imm32
26330     0/imm32/no-imm8
26331     0/imm32/no-disp32
26332     0/imm32/no-xm32
26333     0/imm32/no-x32
26334     0x11/imm32/alloc-id:fake
26335     _Primitive-increment-mem/imm32/next
26336 _Primitive-increment-mem:  # (payload primitive)
26337     0x11/imm32/alloc-id:fake:payload
26338     # increment var => ff 0/subop/increment *(ebp+__)
26339     0x11/imm32/alloc-id:fake
26340     _string-increment/imm32/name
26341     0x11/imm32/alloc-id:fake
26342     Single-int-var-in-mem/imm32/inouts
26343     0/imm32/no-outputs
26344     0/imm32/no-outputs
26345     0x11/imm32/alloc-id:fake
26346     _string_ff_subop_increment/imm32/subx-name
26347     1/imm32/rm32-is-first-inout
26348     0/imm32/no-r32
26349     0/imm32/no-imm32
26350     0/imm32/no-imm8
26351     0/imm32/no-disp32
26352     0/imm32/no-xm32
26353     0/imm32/no-x32
26354     0x11/imm32/alloc-id:fake
26355     _Primitive-increment-reg/imm32/next
26356 _Primitive-increment-reg:  # (payload primitive)
26357     0x11/imm32/alloc-id:fake:payload
26358     # var/reg <- increment => ff 0/subop/increment %__
26359     0x11/imm32/alloc-id:fake
26360     _string-increment/imm32/name
26361     0/imm32/no-inouts
26362     0/imm32/no-inouts
26363     0x11/imm32/alloc-id:fake
26364     Single-int-var-in-some-register/imm32/outputs
26365     0x11/imm32/alloc-id:fake
26366     _string_ff_subop_increment/imm32/subx-name
26367     3/imm32/rm32-is-first-output
26368     0/imm32/no-r32
26369     0/imm32/no-imm32
26370     0/imm32/no-imm8
26371     0/imm32/no-disp32
26372     0/imm32/no-xm32
26373     0/imm32/no-x32
26374     0x11/imm32/alloc-id:fake
26375     _Primitive-decrement-mem/imm32/next
26376 _Primitive-decrement-mem:  # (payload primitive)
26377     0x11/imm32/alloc-id:fake:payload
26378     # decrement var => ff 1/subop/decrement *(ebp+__)
26379     0x11/imm32/alloc-id:fake
26380     _string-decrement/imm32/name
26381     0x11/imm32/alloc-id:fake
26382     Single-int-var-in-mem/imm32/inouts
26383     0/imm32/no-outputs
26384     0/imm32/no-outputs
26385     0x11/imm32/alloc-id:fake
26386     _string_ff_subop_decrement/imm32/subx-name
26387     1/imm32/rm32-is-first-inout
26388     0/imm32/no-r32
26389     0/imm32/no-imm32
26390     0/imm32/no-imm8
26391     0/imm32/no-disp32
26392     0/imm32/no-xm32
26393     0/imm32/no-x32
26394     0x11/imm32/alloc-id:fake
26395     _Primitive-decrement-reg/imm32/next
26396 _Primitive-decrement-reg:  # (payload primitive)
26397     0x11/imm32/alloc-id:fake:payload
26398     # var/reg <- decrement => ff 1/subop/decrement %__
26399     0x11/imm32/alloc-id:fake
26400     _string-decrement/imm32/name
26401     0/imm32/no-inouts
26402     0/imm32/no-inouts
26403     0x11/imm32/alloc-id:fake
26404     Single-int-var-in-some-register/imm32/outputs
26405     0x11/imm32/alloc-id:fake
26406     _string_ff_subop_decrement/imm32/subx-name
26407     3/imm32/rm32-is-first-output
26408     0/imm32/no-r32
26409     0/imm32/no-imm32
26410     0/imm32/no-imm8
26411     0/imm32/no-disp32
26412     0/imm32/no-xm32
26413     0/imm32/no-x32
26414     0x11/imm32/alloc-id:fake
26415     _Primitive-add-to-eax/imm32/next
26416 # - add
26417 _Primitive-add-to-eax:  # (payload primitive)
26418     0x11/imm32/alloc-id:fake:payload
26419     # var/eax <- add lit => 05/add-to-eax lit/imm32
26420     0x11/imm32/alloc-id:fake
26421     _string-add/imm32/name
26422     0x11/imm32/alloc-id:fake
26423     Single-lit-var/imm32/inouts
26424     0x11/imm32/alloc-id:fake
26425     Single-int-var-in-eax/imm32/outputs
26426     0x11/imm32/alloc-id:fake
26427     _string_05_add_to_eax/imm32/subx-name
26428     0/imm32/no-rm32
26429     0/imm32/no-r32
26430     1/imm32/imm32-is-first-inout
26431     0/imm32/no-imm8
26432     0/imm32/no-disp32
26433     0/imm32/no-xm32
26434     0/imm32/no-x32
26435     0x11/imm32/alloc-id:fake
26436     _Primitive-add-reg-to-reg/imm32/next
26437 _Primitive-add-reg-to-reg:  # (payload primitive)
26438     0x11/imm32/alloc-id:fake:payload
26439     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
26440     0x11/imm32/alloc-id:fake
26441     _string-add/imm32/name
26442     0x11/imm32/alloc-id:fake
26443     Single-int-var-in-some-register/imm32/inouts
26444     0x11/imm32/alloc-id:fake
26445     Single-int-var-in-some-register/imm32/outputs
26446     0x11/imm32/alloc-id:fake
26447     _string_01_add_to/imm32/subx-name
26448     3/imm32/rm32-is-first-output
26449     1/imm32/r32-is-first-inout
26450     0/imm32/no-imm32
26451     0/imm32/no-imm8
26452     0/imm32/no-disp32
26453     0/imm32/no-xm32
26454     0/imm32/no-x32
26455     0x11/imm32/alloc-id:fake
26456     _Primitive-add-reg-to-mem/imm32/next
26457 _Primitive-add-reg-to-mem:  # (payload primitive)
26458     0x11/imm32/alloc-id:fake:payload
26459     # add-to var1 var2/reg => 01/add-to var1 var2/r32
26460     0x11/imm32/alloc-id:fake
26461     _string-add-to/imm32/name
26462     0x11/imm32/alloc-id:fake
26463     Two-args-int-stack-int-reg/imm32/inouts
26464     0/imm32/no-outputs
26465     0/imm32/no-outputs
26466     0x11/imm32/alloc-id:fake
26467     _string_01_add_to/imm32/subx-name
26468     1/imm32/rm32-is-first-inout
26469     2/imm32/r32-is-second-inout
26470     0/imm32/no-imm32
26471     0/imm32/no-imm8
26472     0/imm32/no-disp32
26473     0/imm32/no-xm32
26474     0/imm32/no-x32
26475     0x11/imm32/alloc-id:fake
26476     _Primitive-add-mem-to-reg/imm32/next
26477 _Primitive-add-mem-to-reg:  # (payload primitive)
26478     0x11/imm32/alloc-id:fake:payload
26479     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
26480     0x11/imm32/alloc-id:fake
26481     _string-add/imm32/name
26482     0x11/imm32/alloc-id:fake
26483     Single-int-var-in-mem/imm32/inouts
26484     0x11/imm32/alloc-id:fake
26485     Single-int-var-in-some-register/imm32/outputs
26486     0x11/imm32/alloc-id:fake
26487     _string_03_add/imm32/subx-name
26488     1/imm32/rm32-is-first-inout
26489     3/imm32/r32-is-first-output
26490     0/imm32/no-imm32
26491     0/imm32/no-imm8
26492     0/imm32/no-disp32
26493     0/imm32/no-xm32
26494     0/imm32/no-x32
26495     0x11/imm32/alloc-id:fake
26496     _Primitive-add-lit-to-reg/imm32/next
26497 _Primitive-add-lit-to-reg:  # (payload primitive)
26498     0x11/imm32/alloc-id:fake:payload
26499     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
26500     0x11/imm32/alloc-id:fake
26501     _string-add/imm32/name
26502     0x11/imm32/alloc-id:fake
26503     Single-lit-var/imm32/inouts
26504     0x11/imm32/alloc-id:fake
26505     Single-int-var-in-some-register/imm32/outputs
26506     0x11/imm32/alloc-id:fake
26507     _string_81_subop_add/imm32/subx-name
26508     3/imm32/rm32-is-first-output
26509     0/imm32/no-r32
26510     1/imm32/imm32-is-first-inout
26511     0/imm32/no-imm8
26512     0/imm32/no-disp32
26513     0/imm32/no-xm32
26514     0/imm32/no-x32
26515     0x11/imm32/alloc-id:fake
26516     _Primitive-add-lit-to-mem/imm32/next
26517 _Primitive-add-lit-to-mem:  # (payload primitive)
26518     0x11/imm32/alloc-id:fake:payload
26519     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
26520     0x11/imm32/alloc-id:fake
26521     _string-add-to/imm32/name
26522     0x11/imm32/alloc-id:fake
26523     Int-var-and-literal/imm32/inouts
26524     0/imm32/no-outputs
26525     0/imm32/no-outputs
26526     0x11/imm32/alloc-id:fake
26527     _string_81_subop_add/imm32/subx-name
26528     1/imm32/rm32-is-first-inout
26529     0/imm32/no-r32
26530     2/imm32/imm32-is-second-inout
26531     0/imm32/no-imm8
26532     0/imm32/no-disp32
26533     0/imm32/no-xm32
26534     0/imm32/no-x32
26535     0x11/imm32/alloc-id:fake
26536     _Primitive-subtract-from-eax/imm32/next
26537 # - subtract
26538 _Primitive-subtract-from-eax:  # (payload primitive)
26539     0x11/imm32/alloc-id:fake:payload
26540     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
26541     0x11/imm32/alloc-id:fake
26542     _string-subtract/imm32/name
26543     0x11/imm32/alloc-id:fake
26544     Single-lit-var/imm32/inouts
26545     0x11/imm32/alloc-id:fake
26546     Single-int-var-in-eax/imm32/outputs
26547     0x11/imm32/alloc-id:fake
26548     _string_2d_subtract_from_eax/imm32/subx-name
26549     0/imm32/no-rm32
26550     0/imm32/no-r32
26551     1/imm32/imm32-is-first-inout
26552     0/imm32/no-imm8
26553     0/imm32/no-disp32
26554     0/imm32/no-xm32
26555     0/imm32/no-x32
26556     0x11/imm32/alloc-id:fake
26557     _Primitive-subtract-reg-from-reg/imm32/next
26558 _Primitive-subtract-reg-from-reg:  # (payload primitive)
26559     0x11/imm32/alloc-id:fake:payload
26560     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
26561     0x11/imm32/alloc-id:fake
26562     _string-subtract/imm32/name
26563     0x11/imm32/alloc-id:fake
26564     Single-int-var-in-some-register/imm32/inouts
26565     0x11/imm32/alloc-id:fake
26566     Single-int-var-in-some-register/imm32/outputs
26567     0x11/imm32/alloc-id:fake
26568     _string_29_subtract_from/imm32/subx-name
26569     3/imm32/rm32-is-first-output
26570     1/imm32/r32-is-first-inout
26571     0/imm32/no-imm32
26572     0/imm32/no-imm8
26573     0/imm32/no-disp32
26574     0/imm32/no-xm32
26575     0/imm32/no-x32
26576     0x11/imm32/alloc-id:fake
26577     _Primitive-subtract-reg-from-mem/imm32/next
26578 _Primitive-subtract-reg-from-mem:  # (payload primitive)
26579     0x11/imm32/alloc-id:fake:payload
26580     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
26581     0x11/imm32/alloc-id:fake
26582     _string-subtract-from/imm32/name
26583     0x11/imm32/alloc-id:fake
26584     Two-args-int-stack-int-reg/imm32/inouts
26585     0/imm32/no-outputs
26586     0/imm32/no-outputs
26587     0x11/imm32/alloc-id:fake
26588     _string_29_subtract_from/imm32/subx-name
26589     1/imm32/rm32-is-first-inout
26590     2/imm32/r32-is-second-inout
26591     0/imm32/no-imm32
26592     0/imm32/no-imm8
26593     0/imm32/no-disp32
26594     0/imm32/no-xm32
26595     0/imm32/no-x32
26596     0x11/imm32/alloc-id:fake
26597     _Primitive-subtract-mem-from-reg/imm32/next
26598 _Primitive-subtract-mem-from-reg:  # (payload primitive)
26599     0x11/imm32/alloc-id:fake:payload
26600     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
26601     0x11/imm32/alloc-id:fake
26602     _string-subtract/imm32/name
26603     0x11/imm32/alloc-id:fake
26604     Single-int-var-in-mem/imm32/inouts
26605     0x11/imm32/alloc-id:fake
26606     Single-int-var-in-some-register/imm32/outputs
26607     0x11/imm32/alloc-id:fake
26608     _string_2b_subtract/imm32/subx-name
26609     1/imm32/rm32-is-first-inout
26610     3/imm32/r32-is-first-output
26611     0/imm32/no-imm32
26612     0/imm32/no-imm8
26613     0/imm32/no-disp32
26614     0/imm32/no-xm32
26615     0/imm32/no-x32
26616     0x11/imm32/alloc-id:fake
26617     _Primitive-subtract-lit-from-reg/imm32/next
26618 _Primitive-subtract-lit-from-reg:  # (payload primitive)
26619     0x11/imm32/alloc-id:fake:payload
26620     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
26621     0x11/imm32/alloc-id:fake
26622     _string-subtract/imm32/name
26623     0x11/imm32/alloc-id:fake
26624     Single-lit-var/imm32/inouts
26625     0x11/imm32/alloc-id:fake
26626     Single-int-var-in-some-register/imm32/outputs
26627     0x11/imm32/alloc-id:fake
26628     _string_81_subop_subtract/imm32/subx-name
26629     3/imm32/rm32-is-first-output
26630     0/imm32/no-r32
26631     1/imm32/imm32-is-first-inout
26632     0/imm32/no-imm8
26633     0/imm32/no-disp32
26634     0/imm32/no-xm32
26635     0/imm32/no-x32
26636     0x11/imm32/alloc-id:fake
26637     _Primitive-subtract-lit-from-mem/imm32/next
26638 _Primitive-subtract-lit-from-mem:  # (payload primitive)
26639     0x11/imm32/alloc-id:fake:payload
26640     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
26641     0x11/imm32/alloc-id:fake
26642     _string-subtract-from/imm32/name
26643     0x11/imm32/alloc-id:fake
26644     Int-var-and-literal/imm32/inouts
26645     0/imm32/no-outputs
26646     0/imm32/no-outputs
26647     0x11/imm32/alloc-id:fake
26648     _string_81_subop_subtract/imm32/subx-name
26649     1/imm32/rm32-is-first-inout
26650     0/imm32/no-r32
26651     2/imm32/imm32-is-second-inout
26652     0/imm32/no-imm8
26653     0/imm32/no-disp32
26654     0/imm32/no-xm32
26655     0/imm32/no-x32
26656     0x11/imm32/alloc-id:fake
26657     _Primitive-and-with-eax/imm32/next
26658 # - and
26659 _Primitive-and-with-eax:  # (payload primitive)
26660     0x11/imm32/alloc-id:fake:payload
26661     # var/eax <- and lit => 25/and-with-eax lit/imm32
26662     0x11/imm32/alloc-id:fake
26663     _string-and/imm32/name
26664     0x11/imm32/alloc-id:fake
26665     Single-lit-var/imm32/inouts
26666     0x11/imm32/alloc-id:fake
26667     Single-int-var-in-eax/imm32/outputs
26668     0x11/imm32/alloc-id:fake
26669     _string_25_and_with_eax/imm32/subx-name
26670     0/imm32/no-rm32
26671     0/imm32/no-r32
26672     1/imm32/imm32-is-first-inout
26673     0/imm32/no-imm8
26674     0/imm32/no-disp32
26675     0/imm32/no-xm32
26676     0/imm32/no-x32
26677     0x11/imm32/alloc-id:fake
26678     _Primitive-and-reg-with-reg/imm32/next
26679 _Primitive-and-reg-with-reg:  # (payload primitive)
26680     0x11/imm32/alloc-id:fake:payload
26681     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
26682     0x11/imm32/alloc-id:fake
26683     _string-and/imm32/name
26684     0x11/imm32/alloc-id:fake
26685     Single-int-var-in-some-register/imm32/inouts
26686     0x11/imm32/alloc-id:fake
26687     Single-int-var-in-some-register/imm32/outputs
26688     0x11/imm32/alloc-id:fake
26689     _string_21_and_with/imm32/subx-name
26690     3/imm32/rm32-is-first-output
26691     1/imm32/r32-is-first-inout
26692     0/imm32/no-imm32
26693     0/imm32/no-imm8
26694     0/imm32/no-disp32
26695     0/imm32/no-xm32
26696     0/imm32/no-x32
26697     0x11/imm32/alloc-id:fake
26698     _Primitive-and-reg-with-mem/imm32/next
26699 _Primitive-and-reg-with-mem:  # (payload primitive)
26700     0x11/imm32/alloc-id:fake:payload
26701     # and-with var1 var2/reg => 21/and-with var1 var2/r32
26702     0x11/imm32/alloc-id:fake
26703     _string-and-with/imm32/name
26704     0x11/imm32/alloc-id:fake
26705     Two-args-int-stack-int-reg/imm32/inouts
26706     0/imm32/no-outputs
26707     0/imm32/no-outputs
26708     0x11/imm32/alloc-id:fake
26709     _string_21_and_with/imm32/subx-name
26710     1/imm32/rm32-is-first-inout
26711     2/imm32/r32-is-second-inout
26712     0/imm32/no-imm32
26713     0/imm32/no-imm8
26714     0/imm32/no-disp32
26715     0/imm32/no-xm32
26716     0/imm32/no-x32
26717     0x11/imm32/alloc-id:fake
26718     _Primitive-and-mem-with-reg/imm32/next
26719 _Primitive-and-mem-with-reg:  # (payload primitive)
26720     0x11/imm32/alloc-id:fake:payload
26721     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
26722     0x11/imm32/alloc-id:fake
26723     _string-and/imm32/name
26724     0x11/imm32/alloc-id:fake
26725     Single-int-var-in-mem/imm32/inouts
26726     0x11/imm32/alloc-id:fake
26727     Single-int-var-in-some-register/imm32/outputs
26728     0x11/imm32/alloc-id:fake
26729     _string_23_and/imm32/subx-name
26730     1/imm32/rm32-is-first-inout
26731     3/imm32/r32-is-first-output
26732     0/imm32/no-imm32
26733     0/imm32/no-imm8
26734     0/imm32/no-disp32
26735     0/imm32/no-xm32
26736     0/imm32/no-x32
26737     0x11/imm32/alloc-id:fake
26738     _Primitive-and-lit-with-reg/imm32/next
26739 _Primitive-and-lit-with-reg:  # (payload primitive)
26740     0x11/imm32/alloc-id:fake:payload
26741     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
26742     0x11/imm32/alloc-id:fake
26743     _string-and/imm32/name
26744     0x11/imm32/alloc-id:fake
26745     Single-lit-var/imm32/inouts
26746     0x11/imm32/alloc-id:fake
26747     Single-int-var-in-some-register/imm32/outputs
26748     0x11/imm32/alloc-id:fake
26749     _string_81_subop_and/imm32/subx-name
26750     3/imm32/rm32-is-first-output
26751     0/imm32/no-r32
26752     1/imm32/imm32-is-first-inout
26753     0/imm32/no-imm8
26754     0/imm32/no-disp32
26755     0/imm32/no-xm32
26756     0/imm32/no-x32
26757     0x11/imm32/alloc-id:fake
26758     _Primitive-and-lit-with-mem/imm32/next
26759 _Primitive-and-lit-with-mem:  # (payload primitive)
26760     0x11/imm32/alloc-id:fake:payload
26761     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
26762     0x11/imm32/alloc-id:fake
26763     _string-and-with/imm32/name
26764     0x11/imm32/alloc-id:fake
26765     Int-var-and-literal/imm32/inouts
26766     0/imm32/no-outputs
26767     0/imm32/no-outputs
26768     0x11/imm32/alloc-id:fake
26769     _string_81_subop_and/imm32/subx-name
26770     1/imm32/rm32-is-first-inout
26771     0/imm32/no-r32
26772     2/imm32/imm32-is-second-inout
26773     0/imm32/no-imm8
26774     0/imm32/no-disp32
26775     0/imm32/no-xm32
26776     0/imm32/no-x32
26777     0x11/imm32/alloc-id:fake
26778     _Primitive-or-with-eax/imm32/next
26779 # - or
26780 _Primitive-or-with-eax:  # (payload primitive)
26781     0x11/imm32/alloc-id:fake:payload
26782     # var/eax <- or lit => 0d/or-with-eax lit/imm32
26783     0x11/imm32/alloc-id:fake
26784     _string-or/imm32/name
26785     0x11/imm32/alloc-id:fake
26786     Single-lit-var/imm32/inouts
26787     0x11/imm32/alloc-id:fake
26788     Single-int-var-in-eax/imm32/outputs
26789     0x11/imm32/alloc-id:fake
26790     _string_0d_or_with_eax/imm32/subx-name
26791     0/imm32/no-rm32
26792     0/imm32/no-r32
26793     1/imm32/imm32-is-first-inout
26794     0/imm32/no-imm8
26795     0/imm32/no-disp32
26796     0/imm32/no-xm32
26797     0/imm32/no-x32
26798     0x11/imm32/alloc-id:fake
26799     _Primitive-or-reg-with-reg/imm32/next
26800 _Primitive-or-reg-with-reg:  # (payload primitive)
26801     0x11/imm32/alloc-id:fake:payload
26802     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
26803     0x11/imm32/alloc-id:fake
26804     _string-or/imm32/name
26805     0x11/imm32/alloc-id:fake
26806     Single-int-var-in-some-register/imm32/inouts
26807     0x11/imm32/alloc-id:fake
26808     Single-int-var-in-some-register/imm32/outputs
26809     0x11/imm32/alloc-id:fake
26810     _string_09_or_with/imm32/subx-name
26811     3/imm32/rm32-is-first-output
26812     1/imm32/r32-is-first-inout
26813     0/imm32/no-imm32
26814     0/imm32/no-imm8
26815     0/imm32/no-disp32
26816     0/imm32/no-xm32
26817     0/imm32/no-x32
26818     0x11/imm32/alloc-id:fake
26819     _Primitive-or-reg-with-mem/imm32/next
26820 _Primitive-or-reg-with-mem:  # (payload primitive)
26821     0x11/imm32/alloc-id:fake:payload
26822     # or-with var1 var2/reg => 09/or-with var1 var2/r32
26823     0x11/imm32/alloc-id:fake
26824     _string-or-with/imm32/name
26825     0x11/imm32/alloc-id:fake
26826     Two-args-int-stack-int-reg/imm32/inouts
26827     0/imm32/no-outputs
26828     0/imm32/no-outputs
26829     0x11/imm32/alloc-id:fake
26830     _string_09_or_with/imm32/subx-name
26831     1/imm32/rm32-is-first-inout
26832     2/imm32/r32-is-second-inout
26833     0/imm32/no-imm32
26834     0/imm32/no-imm8
26835     0/imm32/no-disp32
26836     0/imm32/no-xm32
26837     0/imm32/no-x32
26838     0x11/imm32/alloc-id:fake
26839     _Primitive-or-mem-with-reg/imm32/next
26840 _Primitive-or-mem-with-reg:  # (payload primitive)
26841     0x11/imm32/alloc-id:fake:payload
26842     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
26843     0x11/imm32/alloc-id:fake
26844     _string-or/imm32/name
26845     0x11/imm32/alloc-id:fake
26846     Single-int-var-in-mem/imm32/inouts
26847     0x11/imm32/alloc-id:fake
26848     Single-int-var-in-some-register/imm32/outputs
26849     0x11/imm32/alloc-id:fake
26850     _string_0b_or/imm32/subx-name
26851     1/imm32/rm32-is-first-inout
26852     3/imm32/r32-is-first-output
26853     0/imm32/no-imm32
26854     0/imm32/no-imm8
26855     0/imm32/no-disp32
26856     0/imm32/no-xm32
26857     0/imm32/no-x32
26858     0x11/imm32/alloc-id:fake
26859     _Primitive-or-lit-with-reg/imm32/next
26860 _Primitive-or-lit-with-reg:  # (payload primitive)
26861     0x11/imm32/alloc-id:fake:payload
26862     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
26863     0x11/imm32/alloc-id:fake
26864     _string-or/imm32/name
26865     0x11/imm32/alloc-id:fake
26866     Single-lit-var/imm32/inouts
26867     0x11/imm32/alloc-id:fake
26868     Single-int-var-in-some-register/imm32/outputs
26869     0x11/imm32/alloc-id:fake
26870     _string_81_subop_or/imm32/subx-name
26871     3/imm32/rm32-is-first-output
26872     0/imm32/no-r32
26873     1/imm32/imm32-is-first-inout
26874     0/imm32/no-imm8
26875     0/imm32/no-disp32
26876     0/imm32/no-xm32
26877     0/imm32/no-x32
26878     0x11/imm32/alloc-id:fake
26879     _Primitive-or-lit-with-mem/imm32/next
26880 _Primitive-or-lit-with-mem:  # (payload primitive)
26881     0x11/imm32/alloc-id:fake:payload
26882     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
26883     0x11/imm32/alloc-id:fake
26884     _string-or-with/imm32/name
26885     0x11/imm32/alloc-id:fake
26886     Int-var-and-literal/imm32/inouts
26887     0/imm32/no-outputs
26888     0/imm32/no-outputs
26889     0x11/imm32/alloc-id:fake
26890     _string_81_subop_or/imm32/subx-name
26891     1/imm32/rm32-is-first-inout
26892     0/imm32/no-r32
26893     2/imm32/imm32-is-second-inout
26894     0/imm32/no-imm8
26895     0/imm32/no-disp32
26896     0/imm32/no-xm32
26897     0/imm32/no-x32
26898     0x11/imm32/alloc-id:fake
26899     _Primitive-xor-with-eax/imm32/next
26900 # - xor
26901 _Primitive-xor-with-eax:  # (payload primitive)
26902     0x11/imm32/alloc-id:fake:payload
26903     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
26904     0x11/imm32/alloc-id:fake
26905     _string-xor/imm32/name
26906     0x11/imm32/alloc-id:fake
26907     Single-lit-var/imm32/inouts
26908     0x11/imm32/alloc-id:fake
26909     Single-int-var-in-eax/imm32/outputs
26910     0x11/imm32/alloc-id:fake
26911     _string_35_xor_with_eax/imm32/subx-name
26912     0/imm32/no-rm32
26913     0/imm32/no-r32
26914     1/imm32/imm32-is-first-inout
26915     0/imm32/no-imm8
26916     0/imm32/no-disp32
26917     0/imm32/no-xm32
26918     0/imm32/no-x32
26919     0x11/imm32/alloc-id:fake
26920     _Primitive-xor-reg-with-reg/imm32/next
26921 _Primitive-xor-reg-with-reg:  # (payload primitive)
26922     0x11/imm32/alloc-id:fake:payload
26923     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
26924     0x11/imm32/alloc-id:fake
26925     _string-xor/imm32/name
26926     0x11/imm32/alloc-id:fake
26927     Single-int-var-in-some-register/imm32/inouts
26928     0x11/imm32/alloc-id:fake
26929     Single-int-var-in-some-register/imm32/outputs
26930     0x11/imm32/alloc-id:fake
26931     _string_31_xor_with/imm32/subx-name
26932     3/imm32/rm32-is-first-output
26933     1/imm32/r32-is-first-inout
26934     0/imm32/no-imm32
26935     0/imm32/no-imm8
26936     0/imm32/no-disp32
26937     0/imm32/no-xm32
26938     0/imm32/no-x32
26939     0x11/imm32/alloc-id:fake
26940     _Primitive-xor-reg-with-mem/imm32/next
26941 _Primitive-xor-reg-with-mem:  # (payload primitive)
26942     0x11/imm32/alloc-id:fake:payload
26943     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
26944     0x11/imm32/alloc-id:fake
26945     _string-xor-with/imm32/name
26946     0x11/imm32/alloc-id:fake
26947     Two-args-int-stack-int-reg/imm32/inouts
26948     0/imm32/no-outputs
26949     0/imm32/no-outputs
26950     0x11/imm32/alloc-id:fake
26951     _string_31_xor_with/imm32/subx-name
26952     1/imm32/rm32-is-first-inout
26953     2/imm32/r32-is-second-inout
26954     0/imm32/no-imm32
26955     0/imm32/no-imm8
26956     0/imm32/no-disp32
26957     0/imm32/no-xm32
26958     0/imm32/no-x32
26959     0x11/imm32/alloc-id:fake
26960     _Primitive-xor-mem-with-reg/imm32/next
26961 _Primitive-xor-mem-with-reg:  # (payload primitive)
26962     0x11/imm32/alloc-id:fake:payload
26963     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
26964     0x11/imm32/alloc-id:fake
26965     _string-xor/imm32/name
26966     0x11/imm32/alloc-id:fake
26967     Single-int-var-in-mem/imm32/inouts
26968     0x11/imm32/alloc-id:fake
26969     Single-int-var-in-some-register/imm32/outputs
26970     0x11/imm32/alloc-id:fake
26971     _string_33_xor/imm32/subx-name
26972     1/imm32/rm32-is-first-inout
26973     3/imm32/r32-is-first-output
26974     0/imm32/no-imm32
26975     0/imm32/no-imm8
26976     0/imm32/no-disp32
26977     0/imm32/no-xm32
26978     0/imm32/no-x32
26979     0x11/imm32/alloc-id:fake
26980     _Primitive-xor-lit-with-reg/imm32/next
26981 _Primitive-xor-lit-with-reg:  # (payload primitive)
26982     0x11/imm32/alloc-id:fake:payload
26983     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
26984     0x11/imm32/alloc-id:fake
26985     _string-xor/imm32/name
26986     0x11/imm32/alloc-id:fake
26987     Single-lit-var/imm32/inouts
26988     0x11/imm32/alloc-id:fake
26989     Single-int-var-in-some-register/imm32/outputs
26990     0x11/imm32/alloc-id:fake
26991     _string_81_subop_xor/imm32/subx-name
26992     3/imm32/rm32-is-first-output
26993     0/imm32/no-r32
26994     1/imm32/imm32-is-first-inout
26995     0/imm32/no-imm8
26996     0/imm32/no-disp32
26997     0/imm32/no-xm32
26998     0/imm32/no-x32
26999     0x11/imm32/alloc-id:fake
27000     _Primitive-xor-lit-with-mem/imm32/next
27001 _Primitive-xor-lit-with-mem:  # (payload primitive)
27002     0x11/imm32/alloc-id:fake:payload
27003     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
27004     0x11/imm32/alloc-id:fake
27005     _string-xor-with/imm32/name
27006     0x11/imm32/alloc-id:fake
27007     Int-var-and-literal/imm32/inouts
27008     0/imm32/no-outputs
27009     0/imm32/no-outputs
27010     0x11/imm32/alloc-id:fake
27011     _string_81_subop_xor/imm32/subx-name
27012     1/imm32/rm32-is-first-inout
27013     0/imm32/no-r32
27014     2/imm32/imm32-is-second-inout
27015     0/imm32/no-imm8
27016     0/imm32/no-disp32
27017     0/imm32/no-xm32
27018     0/imm32/no-x32
27019     0x11/imm32/alloc-id:fake
27020     _Primitive-shift-reg-left-by-lit/imm32/next
27021 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
27022     0x11/imm32/alloc-id:fake:payload
27023     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
27024     0x11/imm32/alloc-id:fake
27025     _string-shift-left/imm32/name
27026     0x11/imm32/alloc-id:fake
27027     Single-lit-var/imm32/inouts
27028     0x11/imm32/alloc-id:fake
27029     Single-int-var-in-some-register/imm32/outputs
27030     0x11/imm32/alloc-id:fake
27031     _string_c1_subop_shift_left/imm32/subx-name
27032     3/imm32/rm32-is-first-output
27033     0/imm32/no-r32
27034     0/imm32/no-imm32
27035     1/imm32/imm8-is-first-inout
27036     0/imm32/no-disp32
27037     0/imm32/no-xm32
27038     0/imm32/no-x32
27039     0x11/imm32/alloc-id:fake
27040     _Primitive-shift-reg-right-by-lit/imm32/next
27041 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
27042     0x11/imm32/alloc-id:fake:payload
27043     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
27044     0x11/imm32/alloc-id:fake
27045     _string-shift-right/imm32/name
27046     0x11/imm32/alloc-id:fake
27047     Single-lit-var/imm32/inouts
27048     0x11/imm32/alloc-id:fake
27049     Single-int-var-in-some-register/imm32/outputs
27050     0x11/imm32/alloc-id:fake
27051     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
27052     3/imm32/rm32-is-first-output
27053     0/imm32/no-r32
27054     0/imm32/no-imm32
27055     1/imm32/imm8-is-first-inout
27056     0/imm32/no-disp32
27057     0/imm32/no-xm32
27058     0/imm32/no-x32
27059     0x11/imm32/alloc-id:fake
27060     _Primitive-shift-reg-right-signed-by-lit/imm32/next
27061 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
27062     0x11/imm32/alloc-id:fake:payload
27063     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
27064     0x11/imm32/alloc-id:fake
27065     _string-shift-right-signed/imm32/name
27066     0x11/imm32/alloc-id:fake
27067     Single-lit-var/imm32/inouts
27068     0x11/imm32/alloc-id:fake
27069     Single-int-var-in-some-register/imm32/outputs
27070     0x11/imm32/alloc-id:fake
27071     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
27072     3/imm32/rm32-is-first-output
27073     0/imm32/no-r32
27074     0/imm32/no-imm32
27075     1/imm32/imm8-is-first-inout
27076     0/imm32/no-disp32
27077     0/imm32/no-xm32
27078     0/imm32/no-x32
27079     0x11/imm32/alloc-id:fake
27080     _Primitive-shift-mem-left-by-lit/imm32/next
27081 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
27082     0x11/imm32/alloc-id:fake:payload
27083     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
27084     0x11/imm32/alloc-id:fake
27085     _string-shift-left/imm32/name
27086     0x11/imm32/alloc-id:fake
27087     Int-var-and-literal/imm32/inouts
27088     0/imm32/no-outputs
27089     0/imm32/no-outputs
27090     0x11/imm32/alloc-id:fake
27091     _string_c1_subop_shift_left/imm32/subx-name
27092     1/imm32/rm32-is-first-inout
27093     0/imm32/no-r32
27094     0/imm32/no-imm32
27095     2/imm32/imm8-is-second-inout
27096     0/imm32/no-disp32
27097     0/imm32/no-xm32
27098     0/imm32/no-x32
27099     0x11/imm32/alloc-id:fake
27100     _Primitive-shift-mem-right-by-lit/imm32/next
27101 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
27102     0x11/imm32/alloc-id:fake:payload
27103     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
27104     0x11/imm32/alloc-id:fake
27105     _string-shift-right/imm32/name
27106     0x11/imm32/alloc-id:fake
27107     Int-var-and-literal/imm32/inouts
27108     0/imm32/no-outputs
27109     0/imm32/no-outputs
27110     0x11/imm32/alloc-id:fake
27111     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
27112     1/imm32/rm32-is-first-inout
27113     0/imm32/no-r32
27114     0/imm32/no-imm32
27115     2/imm32/imm8-is-second-inout
27116     0/imm32/no-disp32
27117     0/imm32/no-xm32
27118     0/imm32/no-x32
27119     0x11/imm32/alloc-id:fake
27120     _Primitive-shift-mem-right-signed-by-lit/imm32/next
27121 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
27122     0x11/imm32/alloc-id:fake:payload
27123     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
27124     0x11/imm32/alloc-id:fake
27125     _string-shift-right-signed/imm32/name
27126     0x11/imm32/alloc-id:fake
27127     Int-var-and-literal/imm32/inouts
27128     0/imm32/no-outputs
27129     0/imm32/no-outputs
27130     0x11/imm32/alloc-id:fake
27131     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
27132     1/imm32/rm32-is-first-inout
27133     0/imm32/no-r32
27134     0/imm32/no-imm32
27135     2/imm32/imm8-is-second-inout
27136     0/imm32/no-disp32
27137     0/imm32/no-xm32
27138     0/imm32/no-x32
27139     0x11/imm32/alloc-id:fake
27140     _Primitive-copy-to-eax/imm32/next
27141 # - copy
27142 _Primitive-copy-to-eax:  # (payload primitive)
27143     0x11/imm32/alloc-id:fake:payload
27144     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
27145     0x11/imm32/alloc-id:fake
27146     _string-copy/imm32/name
27147     0x11/imm32/alloc-id:fake
27148     Single-lit-var/imm32/inouts
27149     0x11/imm32/alloc-id:fake
27150     Single-int-var-in-eax/imm32/outputs
27151     0x11/imm32/alloc-id:fake
27152     _string_b8_copy_to_eax/imm32/subx-name
27153     0/imm32/no-rm32
27154     0/imm32/no-r32
27155     1/imm32/imm32-is-first-inout
27156     0/imm32/no-imm8
27157     0/imm32/no-disp32
27158     0/imm32/no-xm32
27159     0/imm32/no-x32
27160     0x11/imm32/alloc-id:fake
27161     _Primitive-copy-to-ecx/imm32/next
27162 _Primitive-copy-to-ecx:  # (payload primitive)
27163     0x11/imm32/alloc-id:fake:payload
27164     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
27165     0x11/imm32/alloc-id:fake
27166     _string-copy/imm32/name
27167     0x11/imm32/alloc-id:fake
27168     Single-lit-var/imm32/inouts
27169     0x11/imm32/alloc-id:fake
27170     Single-int-var-in-ecx/imm32/outputs
27171     0x11/imm32/alloc-id:fake
27172     _string_b9_copy_to_ecx/imm32/subx-name
27173     0/imm32/no-rm32
27174     0/imm32/no-r32
27175     1/imm32/imm32-is-first-inout
27176     0/imm32/no-imm8
27177     0/imm32/no-disp32
27178     0/imm32/no-xm32
27179     0/imm32/no-x32
27180     0x11/imm32/alloc-id:fake
27181     _Primitive-copy-to-edx/imm32/next
27182 _Primitive-copy-to-edx:  # (payload primitive)
27183     0x11/imm32/alloc-id:fake:payload
27184     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
27185     0x11/imm32/alloc-id:fake
27186     _string-copy/imm32/name
27187     0x11/imm32/alloc-id:fake
27188     Single-lit-var/imm32/inouts
27189     0x11/imm32/alloc-id:fake
27190     Single-int-var-in-edx/imm32/outputs
27191     0x11/imm32/alloc-id:fake
27192     _string_ba_copy_to_edx/imm32/subx-name
27193     0/imm32/no-rm32
27194     0/imm32/no-r32
27195     1/imm32/imm32-is-first-inout
27196     0/imm32/no-imm8
27197     0/imm32/no-disp32
27198     0/imm32/no-xm32
27199     0/imm32/no-x32
27200     0x11/imm32/alloc-id:fake
27201     _Primitive-copy-to-ebx/imm32/next
27202 _Primitive-copy-to-ebx:  # (payload primitive)
27203     0x11/imm32/alloc-id:fake:payload
27204     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
27205     0x11/imm32/alloc-id:fake
27206     _string-copy/imm32/name
27207     0x11/imm32/alloc-id:fake
27208     Single-lit-var/imm32/inouts
27209     0x11/imm32/alloc-id:fake
27210     Single-int-var-in-ebx/imm32/outputs
27211     0x11/imm32/alloc-id:fake
27212     _string_bb_copy_to_ebx/imm32/subx-name
27213     0/imm32/no-rm32
27214     0/imm32/no-r32
27215     1/imm32/imm32-is-first-inout
27216     0/imm32/no-imm8
27217     0/imm32/no-disp32
27218     0/imm32/no-xm32
27219     0/imm32/no-x32
27220     0x11/imm32/alloc-id:fake
27221     _Primitive-copy-to-esi/imm32/next
27222 _Primitive-copy-to-esi:  # (payload primitive)
27223     0x11/imm32/alloc-id:fake:payload
27224     # var/esi <- copy lit => be/copy-to-esi lit/imm32
27225     0x11/imm32/alloc-id:fake
27226     _string-copy/imm32/name
27227     0x11/imm32/alloc-id:fake
27228     Single-lit-var/imm32/inouts
27229     0x11/imm32/alloc-id:fake
27230     Single-int-var-in-esi/imm32/outputs
27231     0x11/imm32/alloc-id:fake
27232     _string_be_copy_to_esi/imm32/subx-name
27233     0/imm32/no-rm32
27234     0/imm32/no-r32
27235     1/imm32/imm32-is-first-inout
27236     0/imm32/no-imm8
27237     0/imm32/no-disp32
27238     0/imm32/no-xm32
27239     0/imm32/no-x32
27240     0x11/imm32/alloc-id:fake
27241     _Primitive-copy-to-edi/imm32/next
27242 _Primitive-copy-to-edi:  # (payload primitive)
27243     0x11/imm32/alloc-id:fake:payload
27244     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
27245     0x11/imm32/alloc-id:fake
27246     _string-copy/imm32/name
27247     0x11/imm32/alloc-id:fake
27248     Single-lit-var/imm32/inouts
27249     0x11/imm32/alloc-id:fake
27250     Single-int-var-in-edi/imm32/outputs
27251     0x11/imm32/alloc-id:fake
27252     _string_bf_copy_to_edi/imm32/subx-name
27253     0/imm32/no-rm32
27254     0/imm32/no-r32
27255     1/imm32/imm32-is-first-inout
27256     0/imm32/no-imm8
27257     0/imm32/no-disp32
27258     0/imm32/no-xm32
27259     0/imm32/no-x32
27260     0x11/imm32/alloc-id:fake
27261     _Primitive-copy-reg-to-reg/imm32/next
27262 _Primitive-copy-reg-to-reg:  # (payload primitive)
27263     0x11/imm32/alloc-id:fake:payload
27264     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
27265     0x11/imm32/alloc-id:fake
27266     _string-copy/imm32/name
27267     0x11/imm32/alloc-id:fake
27268     Single-int-var-in-some-register/imm32/inouts
27269     0x11/imm32/alloc-id:fake
27270     Single-int-var-in-some-register/imm32/outputs
27271     0x11/imm32/alloc-id:fake
27272     _string_89_<-/imm32/subx-name
27273     3/imm32/rm32-is-first-output
27274     1/imm32/r32-is-first-inout
27275     0/imm32/no-imm32
27276     0/imm32/no-imm8
27277     0/imm32/no-disp32
27278     0/imm32/no-xm32
27279     0/imm32/no-x32
27280     0x11/imm32/alloc-id:fake
27281     _Primitive-copy-reg-to-mem/imm32/next
27282 _Primitive-copy-reg-to-mem:  # (payload primitive)
27283     0x11/imm32/alloc-id:fake:payload
27284     # copy-to var1 var2/reg => 89/<- var1 var2/r32
27285     0x11/imm32/alloc-id:fake
27286     _string-copy-to/imm32/name
27287     0x11/imm32/alloc-id:fake
27288     Two-args-int-stack-int-reg/imm32/inouts
27289     0/imm32/no-outputs
27290     0/imm32/no-outputs
27291     0x11/imm32/alloc-id:fake
27292     _string_89_<-/imm32/subx-name
27293     1/imm32/rm32-is-first-inout
27294     2/imm32/r32-is-second-inout
27295     0/imm32/no-imm32
27296     0/imm32/no-imm8
27297     0/imm32/no-disp32
27298     0/imm32/no-xm32
27299     0/imm32/no-x32
27300     0x11/imm32/alloc-id:fake
27301     _Primitive-copy-mem-to-reg/imm32/next
27302 _Primitive-copy-mem-to-reg:  # (payload primitive)
27303     0x11/imm32/alloc-id:fake:payload
27304     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
27305     0x11/imm32/alloc-id:fake
27306     _string-copy/imm32/name
27307     0x11/imm32/alloc-id:fake
27308     Single-int-var-in-mem/imm32/inouts
27309     0x11/imm32/alloc-id:fake
27310     Single-int-var-in-some-register/imm32/outputs
27311     0x11/imm32/alloc-id:fake
27312     _string_8b_->/imm32/subx-name
27313     1/imm32/rm32-is-first-inout
27314     3/imm32/r32-is-first-output
27315     0/imm32/no-imm32
27316     0/imm32/no-imm8
27317     0/imm32/no-disp32
27318     0/imm32/no-xm32
27319     0/imm32/no-x32
27320     0x11/imm32/alloc-id:fake
27321     _Primitive-copy-lit-to-reg/imm32/next
27322 _Primitive-copy-lit-to-reg:  # (payload primitive)
27323     0x11/imm32/alloc-id:fake:payload
27324     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
27325     0x11/imm32/alloc-id:fake
27326     _string-copy/imm32/name
27327     0x11/imm32/alloc-id:fake
27328     Single-lit-var/imm32/inouts
27329     0x11/imm32/alloc-id:fake
27330     Single-int-var-in-some-register/imm32/outputs
27331     0x11/imm32/alloc-id:fake
27332     _string_c7_subop_copy/imm32/subx-name
27333     3/imm32/rm32-is-first-output
27334     0/imm32/no-r32
27335     1/imm32/imm32-is-first-inout
27336     0/imm32/no-imm8
27337     0/imm32/no-disp32
27338     0/imm32/no-xm32
27339     0/imm32/no-x32
27340     0x11/imm32/alloc-id:fake
27341     _Primitive-copy-lit-to-mem/imm32/next
27342 _Primitive-copy-lit-to-mem:  # (payload primitive)
27343     0x11/imm32/alloc-id:fake:payload
27344     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
27345     0x11/imm32/alloc-id:fake
27346     _string-copy-to/imm32/name
27347     0x11/imm32/alloc-id:fake
27348     Int-var-and-literal/imm32/inouts
27349     0/imm32/no-outputs
27350     0/imm32/no-outputs
27351     0x11/imm32/alloc-id:fake
27352     _string_c7_subop_copy/imm32/subx-name
27353     1/imm32/rm32-is-first-inout
27354     0/imm32/no-r32
27355     2/imm32/imm32-is-second-inout
27356     0/imm32/no-imm8
27357     0/imm32/no-disp32
27358     0/imm32/no-xm32
27359     0/imm32/no-x32
27360     0x11/imm32/alloc-id:fake
27361     _Primitive-copy-byte-from-reg/imm32/next
27362 # - copy byte
27363 _Primitive-copy-byte-from-reg:
27364     0x11/imm32/alloc-id:fake:payload
27365     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
27366     0x11/imm32/alloc-id:fake
27367     _string-copy-byte/imm32/name
27368     0x11/imm32/alloc-id:fake
27369     Single-byte-var-in-some-register/imm32/inouts
27370     0x11/imm32/alloc-id:fake
27371     Single-byte-var-in-some-register/imm32/outputs
27372     0x11/imm32/alloc-id:fake
27373     _string_8a_copy_byte/imm32/subx-name
27374     1/imm32/rm32-is-first-inout
27375     3/imm32/r32-is-first-output
27376     0/imm32/no-imm32
27377     0/imm32/no-imm8
27378     0/imm32/no-disp32
27379     0/imm32/no-xm32
27380     0/imm32/no-x32
27381     0x11/imm32/alloc-id:fake
27382     _Primitive-copy-byte-from-mem/imm32/next
27383 _Primitive-copy-byte-from-mem:
27384     0x11/imm32/alloc-id:fake:payload
27385     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
27386     0x11/imm32/alloc-id:fake
27387     _string-copy-byte/imm32/name
27388     0x11/imm32/alloc-id:fake
27389     Single-byte-var-in-mem/imm32/inouts
27390     0x11/imm32/alloc-id:fake
27391     Single-byte-var-in-some-register/imm32/outputs
27392     0x11/imm32/alloc-id:fake
27393     _string_8a_copy_byte/imm32/subx-name
27394     1/imm32/rm32-is-first-inout
27395     3/imm32/r32-is-first-output
27396     0/imm32/no-imm32
27397     0/imm32/no-imm8
27398     0/imm32/no-disp32
27399     0/imm32/no-xm32
27400     0/imm32/no-x32
27401     0x11/imm32/alloc-id:fake
27402     _Primitive-copy-byte-to-mem/imm32/next
27403 _Primitive-copy-byte-to-mem:
27404     0x11/imm32/alloc-id:fake:payload
27405     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
27406     0x11/imm32/alloc-id:fake
27407     _string-copy-byte-to/imm32/name
27408     0x11/imm32/alloc-id:fake
27409     Two-args-byte-stack-byte-reg/imm32/inouts
27410     0/imm32/no-outputs
27411     0/imm32/no-outputs
27412     0x11/imm32/alloc-id:fake
27413     _string_88_copy_byte/imm32/subx-name
27414     1/imm32/rm32-is-first-inout
27415     2/imm32/r32-is-second-inout
27416     0/imm32/no-imm32
27417     0/imm32/no-imm8
27418     0/imm32/no-disp32
27419     0/imm32/no-xm32
27420     0/imm32/no-x32
27421     0x11/imm32/alloc-id:fake
27422     _Primitive-address/imm32/next
27423 # - address
27424 _Primitive-address:  # (payload primitive)
27425     0x11/imm32/alloc-id:fake:payload
27426     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
27427     0x11/imm32/alloc-id:fake
27428     _string-address/imm32/name
27429     0x11/imm32/alloc-id:fake
27430     Single-int-var-in-mem/imm32/inouts
27431     0x11/imm32/alloc-id:fake
27432     Single-addr-var-in-some-register/imm32/outputs
27433     0x11/imm32/alloc-id:fake
27434     _string_8d_copy_address/imm32/subx-name
27435     1/imm32/rm32-is-first-inout
27436     3/imm32/r32-is-first-output
27437     0/imm32/no-imm32
27438     0/imm32/no-imm8
27439     0/imm32/no-disp32
27440     0/imm32/no-xm32
27441     0/imm32/no-x32
27442     0x11/imm32/alloc-id:fake
27443     _Primitive-compare-reg-with-reg/imm32/next
27444 # - compare
27445 _Primitive-compare-reg-with-reg:  # (payload primitive)
27446     0x11/imm32/alloc-id:fake:payload
27447     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
27448     0x11/imm32/alloc-id:fake
27449     _string-compare/imm32/name
27450     0x11/imm32/alloc-id:fake
27451     Two-int-args-in-regs/imm32/inouts
27452     0/imm32/no-outputs
27453     0/imm32/no-outputs
27454     0x11/imm32/alloc-id:fake
27455     _string_39_compare->/imm32/subx-name
27456     1/imm32/rm32-is-first-inout
27457     2/imm32/r32-is-second-inout
27458     0/imm32/no-imm32
27459     0/imm32/no-imm8
27460     0/imm32/no-disp32
27461     0/imm32/no-xm32
27462     0/imm32/no-x32
27463     0x11/imm32/alloc-id:fake
27464     _Primitive-compare-mem-with-reg/imm32/next
27465 _Primitive-compare-mem-with-reg:  # (payload primitive)
27466     0x11/imm32/alloc-id:fake:payload
27467     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
27468     0x11/imm32/alloc-id:fake
27469     _string-compare/imm32/name
27470     0x11/imm32/alloc-id:fake
27471     Two-args-int-stack-int-reg/imm32/inouts
27472     0/imm32/no-outputs
27473     0/imm32/no-outputs
27474     0x11/imm32/alloc-id:fake
27475     _string_39_compare->/imm32/subx-name
27476     1/imm32/rm32-is-first-inout
27477     2/imm32/r32-is-second-inout
27478     0/imm32/no-imm32
27479     0/imm32/no-imm8
27480     0/imm32/no-disp32
27481     0/imm32/no-xm32
27482     0/imm32/no-x32
27483     0x11/imm32/alloc-id:fake
27484     _Primitive-compare-reg-with-mem/imm32/next
27485 _Primitive-compare-reg-with-mem:  # (payload primitive)
27486     0x11/imm32/alloc-id:fake:payload
27487     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
27488     0x11/imm32/alloc-id:fake
27489     _string-compare/imm32/name
27490     0x11/imm32/alloc-id:fake
27491     Two-args-int-reg-int-stack/imm32/inouts
27492     0/imm32/no-outputs
27493     0/imm32/no-outputs
27494     0x11/imm32/alloc-id:fake
27495     _string_3b_compare<-/imm32/subx-name
27496     2/imm32/rm32-is-second-inout
27497     1/imm32/r32-is-first-inout
27498     0/imm32/no-imm32
27499     0/imm32/no-imm8
27500     0/imm32/no-disp32
27501     0/imm32/no-xm32
27502     0/imm32/no-x32
27503     0x11/imm32/alloc-id:fake
27504     _Primitive-compare-eax-with-literal/imm32/next
27505 _Primitive-compare-eax-with-literal:  # (payload primitive)
27506     0x11/imm32/alloc-id:fake:payload
27507     # compare var1/eax n => 3d/compare-eax-with n/imm32
27508     0x11/imm32/alloc-id:fake
27509     _string-compare/imm32/name
27510     0x11/imm32/alloc-id:fake
27511     Two-args-int-eax-int-literal/imm32/inouts
27512     0/imm32/no-outputs
27513     0/imm32/no-outputs
27514     0x11/imm32/alloc-id:fake
27515     _string_3d_compare_eax_with/imm32/subx-name
27516     0/imm32/no-rm32
27517     0/imm32/no-r32
27518     2/imm32/imm32-is-second-inout
27519     0/imm32/no-imm8
27520     0/imm32/no-disp32
27521     0/imm32/no-xm32
27522     0/imm32/no-x32
27523     0x11/imm32/alloc-id:fake
27524     _Primitive-compare-reg-with-literal/imm32/next
27525 _Primitive-compare-reg-with-literal:  # (payload primitive)
27526     0x11/imm32/alloc-id:fake:payload
27527     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
27528     0x11/imm32/alloc-id:fake
27529     _string-compare/imm32/name
27530     0x11/imm32/alloc-id:fake
27531     Int-var-in-register-and-literal/imm32/inouts
27532     0/imm32/no-outputs
27533     0/imm32/no-outputs
27534     0x11/imm32/alloc-id:fake
27535     _string_81_subop_compare/imm32/subx-name
27536     1/imm32/rm32-is-first-inout
27537     0/imm32/no-r32
27538     2/imm32/imm32-is-second-inout
27539     0/imm32/no-imm8
27540     0/imm32/no-disp32
27541     0/imm32/no-xm32
27542     0/imm32/no-x32
27543     0x11/imm32/alloc-id:fake
27544     _Primitive-compare-mem-with-literal/imm32/next
27545 _Primitive-compare-mem-with-literal:  # (payload primitive)
27546     0x11/imm32/alloc-id:fake:payload
27547     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
27548     0x11/imm32/alloc-id:fake
27549     _string-compare/imm32/name
27550     0x11/imm32/alloc-id:fake
27551     Int-var-and-literal/imm32/inouts
27552     0/imm32/no-outputs
27553     0/imm32/no-outputs
27554     0x11/imm32/alloc-id:fake
27555     _string_81_subop_compare/imm32/subx-name
27556     1/imm32/rm32-is-first-inout
27557     0/imm32/no-r32
27558     2/imm32/imm32-is-second-inout
27559     0/imm32/no-imm8
27560     0/imm32/no-disp32
27561     0/imm32/no-xm32
27562     0/imm32/no-x32
27563     0x11/imm32/alloc-id:fake
27564     _Primitive-negate-reg/imm32/next
27565 # - negate
27566 _Primitive-negate-reg:  # (payload primitive)
27567     0x11/imm32/alloc-id:fake:payload
27568     # var1/reg <- negate => f7 3/subop/negate var1/rm32
27569     0x11/imm32/alloc-id:fake
27570     _string-negate/imm32/name
27571     0/imm32/no-inouts
27572     0/imm32/no-inouts
27573     0x11/imm32/alloc-id:fake
27574     Single-int-var-in-some-register/imm32/outputs
27575     0x11/imm32/alloc-id:fake
27576     _string_f7_subop_negate/imm32/subx-name
27577     3/imm32/rm32-is-first-output
27578     0/imm32/no-r32
27579     0/imm32/no-imm32
27580     0/imm32/no-imm8
27581     0/imm32/no-disp32
27582     0/imm32/no-xm32
27583     0/imm32/no-x32
27584     0x11/imm32/alloc-id:fake
27585     _Primitive-negate-mem/imm32/next
27586 _Primitive-negate-mem:  # (payload primitive)
27587     0x11/imm32/alloc-id:fake:payload
27588     # negate var1 => f7 3/subop/negate var1/rm32
27589     0x11/imm32/alloc-id:fake
27590     _string-negate/imm32/name
27591     0x11/imm32/alloc-id:fake
27592     Single-int-var-in-mem/imm32/inouts
27593     0/imm32/no-outputs
27594     0/imm32/no-outputs
27595     0x11/imm32/alloc-id:fake
27596     _string_f7_subop_negate/imm32/subx-name
27597     1/imm32/rm32-is-first-inout
27598     0/imm32/no-r32
27599     0/imm32/no-imm32
27600     0/imm32/no-imm8
27601     0/imm32/no-disp32
27602     0/imm32/no-xm32
27603     0/imm32/no-x32
27604     0x11/imm32/alloc-id:fake
27605     _Primitive-multiply-reg-by-reg/imm32/next
27606 # - multiply
27607 _Primitive-multiply-reg-by-reg:  # (payload primitive)
27608     0x11/imm32/alloc-id:fake:payload
27609     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
27610     0x11/imm32/alloc-id:fake
27611     _string-multiply/imm32/name
27612     0x11/imm32/alloc-id:fake
27613     Single-int-var-in-some-register/imm32/inouts
27614     0x11/imm32/alloc-id:fake
27615     Single-int-var-in-some-register/imm32/outputs
27616     0x11/imm32/alloc-id:fake
27617     _string_0f_af_multiply/imm32/subx-name
27618     1/imm32/rm32-is-first-inout
27619     3/imm32/r32-is-first-output
27620     0/imm32/no-imm32
27621     0/imm32/no-imm8
27622     0/imm32/no-disp32
27623     0/imm32/no-xm32
27624     0/imm32/no-x32
27625     0x11/imm32/alloc-id:fake
27626     _Primitive-multiply-reg-by-mem/imm32/next
27627 _Primitive-multiply-reg-by-mem:  # (payload primitive)
27628     0x11/imm32/alloc-id:fake:payload
27629     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
27630     0x11/imm32/alloc-id:fake
27631     _string-multiply/imm32/name
27632     0x11/imm32/alloc-id:fake
27633     Single-int-var-in-mem/imm32/inouts
27634     0x11/imm32/alloc-id:fake
27635     Single-int-var-in-some-register/imm32/outputs
27636     0x11/imm32/alloc-id:fake
27637     _string_0f_af_multiply/imm32/subx-name
27638     1/imm32/rm32-is-first-inout
27639     3/imm32/r32-is-first-output
27640     0/imm32/no-imm32
27641     0/imm32/no-imm8
27642     0/imm32/no-disp32
27643     0/imm32/no-xm32
27644     0/imm32/no-x32
27645     0x11/imm32/alloc-id:fake
27646     _Primitive-convert-mem-to-xreg/imm32/next
27647 # - convert int to floating point
27648 _Primitive-convert-mem-to-xreg:  # (payload primitive)
27649     0x11/imm32/alloc-id:fake:payload
27650     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
27651     0x11/imm32/alloc-id:fake
27652     _string-convert/imm32/name
27653     0x11/imm32/alloc-id:fake
27654     Single-int-var-in-mem/imm32/inouts
27655     0x11/imm32/alloc-id:fake
27656     Single-float-var-in-some-register/imm32/outputs
27657     0x11/imm32/alloc-id:fake
27658     _string_f3_0f_2a_convert_to_float/imm32/subx-name
27659     1/imm32/rm32-is-first-inout
27660     0/imm32/no-r32
27661     0/imm32/no-imm32
27662     0/imm32/no-imm8
27663     0/imm32/no-disp32
27664     0/imm32/no-xm32
27665     3/imm32/x32-is-first-output
27666     0x11/imm32/alloc-id:fake
27667     _Primitive-convert-reg-to-xreg/imm32/next
27668 _Primitive-convert-reg-to-xreg:  # (payload primitive)
27669     0x11/imm32/alloc-id:fake:payload
27670     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
27671     0x11/imm32/alloc-id:fake
27672     _string-convert/imm32/name
27673     0x11/imm32/alloc-id:fake
27674     Single-int-var-in-some-register/imm32/inouts
27675     0x11/imm32/alloc-id:fake
27676     Single-float-var-in-some-register/imm32/outputs
27677     0x11/imm32/alloc-id:fake
27678     _string_f3_0f_2a_convert_to_float/imm32/subx-name
27679     1/imm32/rm32-is-first-inout
27680     0/imm32/no-r32
27681     0/imm32/no-imm32
27682     0/imm32/no-imm8
27683     0/imm32/no-disp32
27684     0/imm32/no-xm32
27685     3/imm32/x32-is-first-output
27686     0x11/imm32/alloc-id:fake
27687     _Primitive-convert-xmem-to-reg/imm32/next
27688 # - convert floating point to int
27689 _Primitive-convert-xmem-to-reg:  # (payload primitive)
27690     0x11/imm32/alloc-id:fake:payload
27691     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
27692     0x11/imm32/alloc-id:fake
27693     _string-convert/imm32/name
27694     0x11/imm32/alloc-id:fake
27695     Single-float-var-in-mem/imm32/inouts
27696     0x11/imm32/alloc-id:fake
27697     Single-int-var-in-some-register/imm32/outputs
27698     0x11/imm32/alloc-id:fake
27699     _string_f3_0f_2d_convert_to_int/imm32/subx-name
27700     0/imm32/no-rm32
27701     3/imm32/r32-is-first-output
27702     0/imm32/no-imm32
27703     0/imm32/no-imm8
27704     0/imm32/no-disp32
27705     1/imm32/xm32-is-first-inout
27706     0/imm32/no-x32
27707     0x11/imm32/alloc-id:fake
27708     _Primitive-convert-xreg-to-reg/imm32/next
27709 _Primitive-convert-xreg-to-reg:  # (payload primitive)
27710     0x11/imm32/alloc-id:fake:payload
27711     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
27712     0x11/imm32/alloc-id:fake
27713     _string-convert/imm32/name
27714     0x11/imm32/alloc-id:fake
27715     Single-float-var-in-some-register/imm32/inouts
27716     0x11/imm32/alloc-id:fake
27717     Single-int-var-in-some-register/imm32/outputs
27718     0x11/imm32/alloc-id:fake
27719     _string_f3_0f_2d_convert_to_int/imm32/subx-name
27720     0/imm32/no-rm32
27721     3/imm32/r32-is-first-output
27722     0/imm32/no-imm32
27723     0/imm32/no-imm8
27724     0/imm32/no-disp32
27725     1/imm32/xm32-is-first-inout
27726     0/imm32/no-x32
27727     0x11/imm32/alloc-id:fake
27728     _Primitive-truncate-xmem-to-reg/imm32/next
27729 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
27730     0x11/imm32/alloc-id:fake:payload
27731     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
27732     0x11/imm32/alloc-id:fake
27733     _string-truncate/imm32/name
27734     0x11/imm32/alloc-id:fake
27735     Single-float-var-in-mem/imm32/inouts
27736     0x11/imm32/alloc-id:fake
27737     Single-int-var-in-some-register/imm32/outputs
27738     0x11/imm32/alloc-id:fake
27739     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
27740     0/imm32/no-rm32
27741     3/imm32/r32-is-first-output
27742     0/imm32/no-imm32
27743     0/imm32/no-imm8
27744     0/imm32/no-disp32
27745     1/imm32/xm32-is-first-inout
27746     0/imm32/no-x32
27747     0x11/imm32/alloc-id:fake
27748     _Primitive-truncate-xreg-to-reg/imm32/next
27749 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
27750     0x11/imm32/alloc-id:fake:payload
27751     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
27752     0x11/imm32/alloc-id:fake
27753     _string-truncate/imm32/name
27754     0x11/imm32/alloc-id:fake
27755     Single-float-var-in-some-register/imm32/inouts
27756     0x11/imm32/alloc-id:fake
27757     Single-int-var-in-some-register/imm32/outputs
27758     0x11/imm32/alloc-id:fake
27759     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
27760     0/imm32/no-rm32
27761     3/imm32/r32-is-first-output
27762     0/imm32/no-imm32
27763     0/imm32/no-imm8
27764     0/imm32/no-disp32
27765     1/imm32/xm32-is-first-inout
27766     0/imm32/no-x32
27767     0x11/imm32/alloc-id:fake
27768     _Primitive-reinterpret-xmem-as-reg/imm32/next
27769 # - reinterpret bytes (just for debugging)
27770 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
27771     0x11/imm32/alloc-id:fake:payload
27772     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
27773     0x11/imm32/alloc-id:fake
27774     _string-reinterpret/imm32/name
27775     0x11/imm32/alloc-id:fake
27776     Single-float-var-in-mem/imm32/inouts
27777     0x11/imm32/alloc-id:fake
27778     Single-int-var-in-some-register/imm32/outputs
27779     0x11/imm32/alloc-id:fake
27780     _string_8b_->/imm32/subx-name
27781     0/imm32/no-rm32
27782     3/imm32/r32-is-first-output
27783     0/imm32/no-imm32
27784     0/imm32/no-imm8
27785     0/imm32/no-disp32
27786     1/imm32/xm32-is-first-inout
27787     0/imm32/no-x32
27788     0x11/imm32/alloc-id:fake
27789     _Primitive-reinterpret-mem-as-xreg/imm32/next
27790 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
27791     0x11/imm32/alloc-id:fake:payload
27792     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
27793     0x11/imm32/alloc-id:fake
27794     _string-reinterpret/imm32/name
27795     0x11/imm32/alloc-id:fake
27796     Single-int-var-in-mem/imm32/inouts
27797     0x11/imm32/alloc-id:fake
27798     Single-float-var-in-some-register/imm32/outputs
27799     0x11/imm32/alloc-id:fake
27800     _string_f3_0f_10_copy/imm32/subx-name
27801     1/imm32/rm32-is-first-inout
27802     0/imm32/no-r32
27803     0/imm32/no-imm32
27804     0/imm32/no-imm8
27805     0/imm32/no-disp32
27806     0/imm32/no-xm32
27807     3/imm32/x32-is-first-output
27808     0x11/imm32/alloc-id:fake
27809     _Primitive-copy-xreg-to-xreg/imm32/next
27810 # - floating-point copy
27811 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
27812     0x11/imm32/alloc-id:fake:payload
27813     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
27814     0x11/imm32/alloc-id:fake
27815     _string-copy/imm32/name
27816     0x11/imm32/alloc-id:fake
27817     Single-float-var-in-some-register/imm32/inouts
27818     0x11/imm32/alloc-id:fake
27819     Single-float-var-in-some-register/imm32/outputs
27820     0x11/imm32/alloc-id:fake
27821     _string_f3_0f_11_copy/imm32/subx-name
27822     0/imm32/no-rm32
27823     0/imm32/no-r32
27824     0/imm32/no-imm32
27825     0/imm32/no-imm8
27826     0/imm32/no-disp32
27827     3/imm32/xm32-is-first-output
27828     1/imm32/x32-is-first-inout
27829     0x11/imm32/alloc-id:fake
27830     _Primitive-copy-xreg-to-mem/imm32/next
27831 _Primitive-copy-xreg-to-mem:  # (payload primitive)
27832     0x11/imm32/alloc-id:fake:payload
27833     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
27834     0x11/imm32/alloc-id:fake
27835     _string-copy-to/imm32/name
27836     0x11/imm32/alloc-id:fake
27837     Two-args-float-stack-float-reg/imm32/inouts
27838     0/imm32/no-outputs
27839     0/imm32/no-outputs
27840     0x11/imm32/alloc-id:fake
27841     _string_f3_0f_11_copy/imm32/subx-name
27842     0/imm32/no-rm32
27843     0/imm32/no-r32
27844     0/imm32/no-imm32
27845     0/imm32/no-imm8
27846     0/imm32/no-disp32
27847     1/imm32/xm32-is-first-inout
27848     2/imm32/x32-is-second-inout
27849     0x11/imm32/alloc-id:fake
27850     _Primitive-copy-mem-to-xreg/imm32/next
27851 _Primitive-copy-mem-to-xreg:  # (payload primitive)
27852     0x11/imm32/alloc-id:fake:payload
27853     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
27854     0x11/imm32/alloc-id:fake
27855     _string-copy/imm32/name
27856     0x11/imm32/alloc-id:fake
27857     Single-float-var-in-mem/imm32/inouts
27858     0x11/imm32/alloc-id:fake
27859     Single-float-var-in-some-register/imm32/outputs
27860     0x11/imm32/alloc-id:fake
27861     _string_f3_0f_10_copy/imm32/subx-name
27862     0/imm32/no-rm32
27863     0/imm32/no-r32
27864     0/imm32/no-imm32
27865     0/imm32/no-imm8
27866     0/imm32/no-disp32
27867     1/imm32/xm32-is-first-inout
27868     3/imm32/x32-is-first-output
27869     0x11/imm32/alloc-id:fake
27870     _Primitive-address-of-xmem/imm32/next
27871 # - floating-point-address
27872 _Primitive-address-of-xmem:  # (payload primitive)
27873     0x11/imm32/alloc-id:fake:payload
27874     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
27875     0x11/imm32/alloc-id:fake
27876     _string-address/imm32/name
27877     0x11/imm32/alloc-id:fake
27878     Single-float-var-in-mem/imm32/inouts
27879     0x11/imm32/alloc-id:fake
27880     Single-addr-var-in-some-register/imm32/outputs
27881     0x11/imm32/alloc-id:fake
27882     _string_8d_copy_address/imm32/subx-name
27883     1/imm32/rm32-is-first-inout
27884     3/imm32/r32-is-first-output
27885     0/imm32/no-imm32
27886     0/imm32/no-imm8
27887     0/imm32/no-disp32
27888     0/imm32/no-xm32
27889     0/imm32/no-x32
27890     0x11/imm32/alloc-id:fake
27891     _Primitive-add-xreg-to-xreg/imm32/next
27892 # - floating-point add
27893 _Primitive-add-xreg-to-xreg:  # (payload primitive)
27894     0x11/imm32/alloc-id:fake:payload
27895     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
27896     0x11/imm32/alloc-id:fake
27897     _string-add/imm32/name
27898     0x11/imm32/alloc-id:fake
27899     Single-float-var-in-some-register/imm32/inouts
27900     0x11/imm32/alloc-id:fake
27901     Single-float-var-in-some-register/imm32/outputs
27902     0x11/imm32/alloc-id:fake
27903     _string_f3_0f_58_add/imm32/subx-name
27904     0/imm32/no-rm32
27905     0/imm32/no-r32
27906     0/imm32/no-imm32
27907     0/imm32/no-imm8
27908     0/imm32/no-disp32
27909     1/imm32/xm32-is-first-inout
27910     3/imm32/x32-is-first-output
27911     0x11/imm32/alloc-id:fake
27912     _Primitive-add-mem-to-xreg/imm32/next
27913 _Primitive-add-mem-to-xreg:  # (payload primitive)
27914     0x11/imm32/alloc-id:fake:payload
27915     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
27916     0x11/imm32/alloc-id:fake
27917     _string-add/imm32/name
27918     0x11/imm32/alloc-id:fake
27919     Single-float-var-in-mem/imm32/inouts
27920     0x11/imm32/alloc-id:fake
27921     Single-float-var-in-some-register/imm32/outputs
27922     0x11/imm32/alloc-id:fake
27923     _string_f3_0f_58_add/imm32/subx-name
27924     0/imm32/no-rm32
27925     0/imm32/no-r32
27926     0/imm32/no-imm32
27927     0/imm32/no-imm8
27928     0/imm32/no-disp32
27929     1/imm32/xm32-is-first-inout
27930     3/imm32/x32-is-first-output
27931     0x11/imm32/alloc-id:fake
27932     _Primitive-subtract-xreg-from-xreg/imm32/next
27933 # - floating-point subtract
27934 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
27935     0x11/imm32/alloc-id:fake:payload
27936     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
27937     0x11/imm32/alloc-id:fake
27938     _string-subtract/imm32/name
27939     0x11/imm32/alloc-id:fake
27940     Single-float-var-in-some-register/imm32/inouts
27941     0x11/imm32/alloc-id:fake
27942     Single-float-var-in-some-register/imm32/outputs
27943     0x11/imm32/alloc-id:fake
27944     _string_f3_0f_5c_subtract/imm32/subx-name
27945     0/imm32/no-rm32
27946     0/imm32/no-r32
27947     0/imm32/no-imm32
27948     0/imm32/no-imm8
27949     0/imm32/no-disp32
27950     1/imm32/xm32-is-first-inout
27951     3/imm32/x32-is-first-output
27952     0x11/imm32/alloc-id:fake
27953     _Primitive-subtract-mem-from-xreg/imm32/next
27954 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
27955     0x11/imm32/alloc-id:fake:payload
27956     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
27957     0x11/imm32/alloc-id:fake
27958     _string-subtract/imm32/name
27959     0x11/imm32/alloc-id:fake
27960     Single-float-var-in-mem/imm32/inouts
27961     0x11/imm32/alloc-id:fake
27962     Single-float-var-in-some-register/imm32/outputs
27963     0x11/imm32/alloc-id:fake
27964     _string_f3_0f_5c_subtract/imm32/subx-name
27965     0/imm32/no-rm32
27966     0/imm32/no-r32
27967     0/imm32/no-imm32
27968     0/imm32/no-imm8
27969     0/imm32/no-disp32
27970     1/imm32/xm32-is-first-inout
27971     3/imm32/x32-is-first-output
27972     0x11/imm32/alloc-id:fake
27973     _Primitive-multiply-xreg-by-xreg/imm32/next
27974 # - floating-point multiply
27975 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
27976     0x11/imm32/alloc-id:fake:payload
27977     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
27978     0x11/imm32/alloc-id:fake
27979     _string-multiply/imm32/name
27980     0x11/imm32/alloc-id:fake
27981     Single-float-var-in-some-register/imm32/inouts
27982     0x11/imm32/alloc-id:fake
27983     Single-float-var-in-some-register/imm32/outputs
27984     0x11/imm32/alloc-id:fake
27985     _string_f3_0f_59_multiply/imm32/subx-name
27986     0/imm32/no-rm32
27987     0/imm32/no-r32
27988     0/imm32/no-imm32
27989     0/imm32/no-imm8
27990     0/imm32/no-disp32
27991     1/imm32/xm32-is-first-inout
27992     3/imm32/x32-is-first-output
27993     0x11/imm32/alloc-id:fake
27994     _Primitive-multiply-xreg-by-mem/imm32/next
27995 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
27996     0x11/imm32/alloc-id:fake:payload
27997     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
27998     0x11/imm32/alloc-id:fake
27999     _string-multiply/imm32/name
28000     0x11/imm32/alloc-id:fake
28001     Single-float-var-in-mem/imm32/inouts
28002     0x11/imm32/alloc-id:fake
28003     Single-float-var-in-some-register/imm32/outputs
28004     0x11/imm32/alloc-id:fake
28005     _string_f3_0f_59_multiply/imm32/subx-name
28006     0/imm32/no-rm32
28007     0/imm32/no-r32
28008     0/imm32/no-imm32
28009     0/imm32/no-imm8
28010     0/imm32/no-disp32
28011     1/imm32/xm32-is-first-inout
28012     3/imm32/x32-is-first-output
28013     0x11/imm32/alloc-id:fake
28014     _Primitive-divide-xreg-by-xreg/imm32/next
28015 # - floating-point divide
28016 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
28017     0x11/imm32/alloc-id:fake:payload
28018     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
28019     0x11/imm32/alloc-id:fake
28020     _string-divide/imm32/name
28021     0x11/imm32/alloc-id:fake
28022     Single-float-var-in-some-register/imm32/inouts
28023     0x11/imm32/alloc-id:fake
28024     Single-float-var-in-some-register/imm32/outputs
28025     0x11/imm32/alloc-id:fake
28026     _string_f3_0f_5e_divide/imm32/subx-name
28027     0/imm32/no-rm32
28028     0/imm32/no-r32
28029     0/imm32/no-imm32
28030     0/imm32/no-imm8
28031     0/imm32/no-disp32
28032     1/imm32/xm32-is-first-inout
28033     3/imm32/x32-is-first-output
28034     0x11/imm32/alloc-id:fake
28035     _Primitive-divide-xreg-by-mem/imm32/next
28036 _Primitive-divide-xreg-by-mem:  # (payload primitive)
28037     0x11/imm32/alloc-id:fake:payload
28038     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
28039     0x11/imm32/alloc-id:fake
28040     _string-divide/imm32/name
28041     0x11/imm32/alloc-id:fake
28042     Single-float-var-in-mem/imm32/inouts
28043     0x11/imm32/alloc-id:fake
28044     Single-float-var-in-some-register/imm32/outputs
28045     0x11/imm32/alloc-id:fake
28046     _string_f3_0f_5e_divide/imm32/subx-name
28047     0/imm32/no-rm32
28048     0/imm32/no-r32
28049     0/imm32/no-imm32
28050     0/imm32/no-imm8
28051     0/imm32/no-disp32
28052     1/imm32/xm32-is-first-inout
28053     3/imm32/x32-is-first-output
28054     0x11/imm32/alloc-id:fake
28055     _Primitive-max-xreg-with-xreg/imm32/next
28056 # - floating-point maximum
28057 _Primitive-max-xreg-with-xreg:  # (payload primitive)
28058     0x11/imm32/alloc-id:fake:payload
28059     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
28060     0x11/imm32/alloc-id:fake
28061     _string-max/imm32/name
28062     0x11/imm32/alloc-id:fake
28063     Single-float-var-in-some-register/imm32/inouts
28064     0x11/imm32/alloc-id:fake
28065     Single-float-var-in-some-register/imm32/outputs
28066     0x11/imm32/alloc-id:fake
28067     _string_f3_0f_5f_max/imm32/subx-name
28068     0/imm32/no-rm32
28069     0/imm32/no-r32
28070     0/imm32/no-imm32
28071     0/imm32/no-imm8
28072     0/imm32/no-disp32
28073     1/imm32/xm32-is-first-inout
28074     3/imm32/x32-is-first-output
28075     0x11/imm32/alloc-id:fake
28076     _Primitive-max-xreg-with-mem/imm32/next
28077 _Primitive-max-xreg-with-mem:  # (payload primitive)
28078     0x11/imm32/alloc-id:fake:payload
28079     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
28080     0x11/imm32/alloc-id:fake
28081     _string-max/imm32/name
28082     0x11/imm32/alloc-id:fake
28083     Single-float-var-in-mem/imm32/inouts
28084     0x11/imm32/alloc-id:fake
28085     Single-float-var-in-some-register/imm32/outputs
28086     0x11/imm32/alloc-id:fake
28087     _string_f3_0f_5f_max/imm32/subx-name
28088     0/imm32/no-rm32
28089     0/imm32/no-r32
28090     0/imm32/no-imm32
28091     0/imm32/no-imm8
28092     0/imm32/no-disp32
28093     1/imm32/xm32-is-first-inout
28094     3/imm32/x32-is-first-output
28095     0x11/imm32/alloc-id:fake
28096     _Primitive-min-xreg-with-xreg/imm32/next
28097 # - floating-point minimum
28098 _Primitive-min-xreg-with-xreg:  # (payload primitive)
28099     0x11/imm32/alloc-id:fake:payload
28100     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
28101     0x11/imm32/alloc-id:fake
28102     _string-min/imm32/name
28103     0x11/imm32/alloc-id:fake
28104     Single-float-var-in-some-register/imm32/inouts
28105     0x11/imm32/alloc-id:fake
28106     Single-float-var-in-some-register/imm32/outputs
28107     0x11/imm32/alloc-id:fake
28108     _string_f3_0f_5d_min/imm32/subx-name
28109     0/imm32/no-rm32
28110     0/imm32/no-r32
28111     0/imm32/no-imm32
28112     0/imm32/no-imm8
28113     0/imm32/no-disp32
28114     1/imm32/xm32-is-first-inout
28115     3/imm32/x32-is-first-output
28116     0x11/imm32/alloc-id:fake
28117     _Primitive-min-xreg-with-mem/imm32/next
28118 _Primitive-min-xreg-with-mem:  # (payload primitive)
28119     0x11/imm32/alloc-id:fake:payload
28120     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
28121     0x11/imm32/alloc-id:fake
28122     _string-min/imm32/name
28123     0x11/imm32/alloc-id:fake
28124     Single-float-var-in-mem/imm32/inouts
28125     0x11/imm32/alloc-id:fake
28126     Single-float-var-in-some-register/imm32/outputs
28127     0x11/imm32/alloc-id:fake
28128     _string_f3_0f_5d_min/imm32/subx-name
28129     0/imm32/no-rm32
28130     0/imm32/no-r32
28131     0/imm32/no-imm32
28132     0/imm32/no-imm8
28133     0/imm32/no-disp32
28134     1/imm32/xm32-is-first-inout
28135     3/imm32/x32-is-first-output
28136     0x11/imm32/alloc-id:fake
28137     _Primitive-reciprocal-xreg-to-xreg/imm32/next
28138 # - floating-point reciprocal
28139 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
28140     0x11/imm32/alloc-id:fake:payload
28141     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
28142     0x11/imm32/alloc-id:fake
28143     _string-reciprocal/imm32/name
28144     0x11/imm32/alloc-id:fake
28145     Single-float-var-in-some-register/imm32/inouts
28146     0x11/imm32/alloc-id:fake
28147     Single-float-var-in-some-register/imm32/outputs
28148     0x11/imm32/alloc-id:fake
28149     _string_f3_0f_53_reciprocal/imm32/subx-name
28150     0/imm32/no-rm32
28151     0/imm32/no-r32
28152     0/imm32/no-imm32
28153     0/imm32/no-imm8
28154     0/imm32/no-disp32
28155     1/imm32/xm32-is-first-inout
28156     3/imm32/x32-is-first-output
28157     0x11/imm32/alloc-id:fake
28158     _Primitive-reciprocal-mem-to-xreg/imm32/next
28159 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
28160     0x11/imm32/alloc-id:fake:payload
28161     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
28162     0x11/imm32/alloc-id:fake
28163     _string-reciprocal/imm32/name
28164     0x11/imm32/alloc-id:fake
28165     Single-float-var-in-mem/imm32/inouts
28166     0x11/imm32/alloc-id:fake
28167     Single-float-var-in-some-register/imm32/outputs
28168     0x11/imm32/alloc-id:fake
28169     _string_f3_0f_53_reciprocal/imm32/subx-name
28170     0/imm32/no-rm32
28171     0/imm32/no-r32
28172     0/imm32/no-imm32
28173     0/imm32/no-imm8
28174     0/imm32/no-disp32
28175     1/imm32/xm32-is-first-inout
28176     3/imm32/x32-is-first-output
28177     0x11/imm32/alloc-id:fake
28178     _Primitive-square-root-xreg-to-xreg/imm32/next
28179 # - floating-point square root
28180 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
28181     0x11/imm32/alloc-id:fake:payload
28182     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
28183     0x11/imm32/alloc-id:fake
28184     _string-square-root/imm32/name
28185     0x11/imm32/alloc-id:fake
28186     Single-float-var-in-some-register/imm32/inouts
28187     0x11/imm32/alloc-id:fake
28188     Single-float-var-in-some-register/imm32/outputs
28189     0x11/imm32/alloc-id:fake
28190     _string_f3_0f_51_square_root/imm32/subx-name
28191     0/imm32/no-rm32
28192     0/imm32/no-r32
28193     0/imm32/no-imm32
28194     0/imm32/no-imm8
28195     0/imm32/no-disp32
28196     1/imm32/xm32-is-first-inout
28197     3/imm32/x32-is-first-output
28198     0x11/imm32/alloc-id:fake
28199     _Primitive-square-root-mem-to-xreg/imm32/next
28200 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
28201     0x11/imm32/alloc-id:fake:payload
28202     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
28203     0x11/imm32/alloc-id:fake
28204     _string-square-root/imm32/name
28205     0x11/imm32/alloc-id:fake
28206     Single-float-var-in-mem/imm32/inouts
28207     0x11/imm32/alloc-id:fake
28208     Single-float-var-in-some-register/imm32/outputs
28209     0x11/imm32/alloc-id:fake
28210     _string_f3_0f_51_square_root/imm32/subx-name
28211     0/imm32/no-rm32
28212     0/imm32/no-r32
28213     0/imm32/no-imm32
28214     0/imm32/no-imm8
28215     0/imm32/no-disp32
28216     1/imm32/xm32-is-first-inout
28217     3/imm32/x32-is-first-output
28218     0x11/imm32/alloc-id:fake
28219     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
28220 # - floating-point inverse square root 1/sqrt(x)
28221 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
28222     0x11/imm32/alloc-id:fake:payload
28223     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
28224     0x11/imm32/alloc-id:fake
28225     _string-inverse-square-root/imm32/name
28226     0x11/imm32/alloc-id:fake
28227     Single-float-var-in-some-register/imm32/inouts
28228     0x11/imm32/alloc-id:fake
28229     Single-float-var-in-some-register/imm32/outputs
28230     0x11/imm32/alloc-id:fake
28231     _string_f3_0f_52_inverse_square_root/imm32/subx-name
28232     0/imm32/no-rm32
28233     0/imm32/no-r32
28234     0/imm32/no-imm32
28235     0/imm32/no-imm8
28236     0/imm32/no-disp32
28237     1/imm32/xm32-is-first-inout
28238     3/imm32/x32-is-first-output
28239     0x11/imm32/alloc-id:fake
28240     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
28241 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
28242     0x11/imm32/alloc-id:fake:payload
28243     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
28244     0x11/imm32/alloc-id:fake
28245     _string-inverse-square-root/imm32/name
28246     0x11/imm32/alloc-id:fake
28247     Single-float-var-in-mem/imm32/inouts
28248     0x11/imm32/alloc-id:fake
28249     Single-float-var-in-some-register/imm32/outputs
28250     0x11/imm32/alloc-id:fake
28251     _string_f3_0f_52_inverse_square_root/imm32/subx-name
28252     0/imm32/no-rm32
28253     0/imm32/no-r32
28254     0/imm32/no-imm32
28255     0/imm32/no-imm8
28256     0/imm32/no-disp32
28257     1/imm32/xm32-is-first-inout
28258     3/imm32/x32-is-first-output
28259     0x11/imm32/alloc-id:fake
28260     _Primitive-compare-xreg-with-xreg/imm32/next
28261 # - floating-point compare
28262 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
28263     0x11/imm32/alloc-id:fake:payload
28264     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
28265     0x11/imm32/alloc-id:fake
28266     _string-compare/imm32/name
28267     0x11/imm32/alloc-id:fake
28268     Two-float-args-in-regs/imm32/inouts
28269     0/imm32/no-outputs
28270     0/imm32/no-outputs
28271     0x11/imm32/alloc-id:fake
28272     _string_0f_2f_compare/imm32/subx-name
28273     0/imm32/no-rm32
28274     0/imm32/no-r32
28275     0/imm32/no-imm32
28276     0/imm32/no-imm8
28277     0/imm32/no-disp32
28278     1/imm32/xm32-is-first-inout
28279     2/imm32/x32-is-second-inout
28280     0x11/imm32/alloc-id:fake
28281     _Primitive-compare-xreg-with-mem/imm32/next
28282 _Primitive-compare-xreg-with-mem:  # (payload primitive)
28283     0x11/imm32/alloc-id:fake:payload
28284     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
28285     0x11/imm32/alloc-id:fake
28286     _string-compare/imm32/name
28287     0x11/imm32/alloc-id:fake
28288     Two-args-float-reg-float-stack/imm32/inouts
28289     0/imm32/no-outputs
28290     0/imm32/no-outputs
28291     0x11/imm32/alloc-id:fake
28292     _string_0f_2f_compare/imm32/subx-name
28293     0/imm32/no-rm32
28294     0/imm32/no-r32
28295     0/imm32/no-imm32
28296     0/imm32/no-imm8
28297     0/imm32/no-disp32
28298     2/imm32/xm32-is-second-inout
28299     1/imm32/x32-is-first-inout
28300     0x11/imm32/alloc-id:fake
28301     _Primitive-break-if-addr</imm32/next
28302 # - branches
28303 _Primitive-break-if-addr<:  # (payload primitive)
28304     0x11/imm32/alloc-id:fake:payload
28305     0x11/imm32/alloc-id:fake
28306     _string-break-if-addr</imm32/name
28307     0/imm32/no-inouts
28308     0/imm32/no-inouts
28309     0/imm32/no-outputs
28310     0/imm32/no-outputs
28311     0x11/imm32/alloc-id:fake
28312     _string_0f_82_jump_break/imm32/subx-name
28313     0/imm32/no-rm32
28314     0/imm32/no-r32
28315     0/imm32/no-imm32
28316     0/imm32/no-imm8
28317     0/imm32/no-disp32
28318     0/imm32/no-xm32
28319     0/imm32/no-x32
28320     0x11/imm32/alloc-id:fake
28321     _Primitive-break-if-addr>=/imm32/next
28322 _Primitive-break-if-addr>=:  # (payload primitive)
28323     0x11/imm32/alloc-id:fake:payload
28324     0x11/imm32/alloc-id:fake
28325     _string-break-if-addr>=/imm32/name
28326     0/imm32/no-inouts
28327     0/imm32/no-inouts
28328     0/imm32/no-outputs
28329     0/imm32/no-outputs
28330     0x11/imm32/alloc-id:fake
28331     _string_0f_83_jump_break/imm32/subx-name
28332     0/imm32/no-rm32
28333     0/imm32/no-r32
28334     0/imm32/no-imm32
28335     0/imm32/no-imm8
28336     0/imm32/no-disp32
28337     0/imm32/no-xm32
28338     0/imm32/no-x32
28339     0x11/imm32/alloc-id:fake
28340     _Primitive-break-if-=/imm32/next
28341 _Primitive-break-if-=:  # (payload primitive)
28342     0x11/imm32/alloc-id:fake:payload
28343     0x11/imm32/alloc-id:fake
28344     _string-break-if-=/imm32/name
28345     0/imm32/no-inouts
28346     0/imm32/no-inouts
28347     0/imm32/no-outputs
28348     0/imm32/no-outputs
28349     0x11/imm32/alloc-id:fake
28350     _string_0f_84_jump_break/imm32/subx-name
28351     0/imm32/no-rm32
28352     0/imm32/no-r32
28353     0/imm32/no-imm32
28354     0/imm32/no-imm8
28355     0/imm32/no-disp32
28356     0/imm32/no-xm32
28357     0/imm32/no-x32
28358     0x11/imm32/alloc-id:fake
28359     _Primitive-break-if-!=/imm32/next
28360 _Primitive-break-if-!=:  # (payload primitive)
28361     0x11/imm32/alloc-id:fake:payload
28362     0x11/imm32/alloc-id:fake
28363     _string-break-if-!=/imm32/name
28364     0/imm32/no-inouts
28365     0/imm32/no-inouts
28366     0/imm32/no-outputs
28367     0/imm32/no-outputs
28368     0x11/imm32/alloc-id:fake
28369     _string_0f_85_jump_break/imm32/subx-name
28370     0/imm32/no-rm32
28371     0/imm32/no-r32
28372     0/imm32/no-imm32
28373     0/imm32/no-imm8
28374     0/imm32/no-disp32
28375     0/imm32/no-xm32
28376     0/imm32/no-x32
28377     0x11/imm32/alloc-id:fake
28378     _Primitive-break-if-addr<=/imm32/next
28379 _Primitive-break-if-addr<=:  # (payload primitive)
28380     0x11/imm32/alloc-id:fake:payload
28381     0x11/imm32/alloc-id:fake
28382     _string-break-if-addr<=/imm32/name
28383     0/imm32/no-inouts
28384     0/imm32/no-inouts
28385     0/imm32/no-outputs
28386     0/imm32/no-outputs
28387     0x11/imm32/alloc-id:fake
28388     _string_0f_86_jump_break/imm32/subx-name
28389     0/imm32/no-rm32
28390     0/imm32/no-r32
28391     0/imm32/no-imm32
28392     0/imm32/no-imm8
28393     0/imm32/no-disp32
28394     0/imm32/no-xm32
28395     0/imm32/no-x32
28396     0x11/imm32/alloc-id:fake
28397     _Primitive-break-if-addr>/imm32/next
28398 _Primitive-break-if-addr>:  # (payload primitive)
28399     0x11/imm32/alloc-id:fake:payload
28400     0x11/imm32/alloc-id:fake
28401     _string-break-if-addr>/imm32/name
28402     0/imm32/no-inouts
28403     0/imm32/no-inouts
28404     0/imm32/no-outputs
28405     0/imm32/no-outputs
28406     0x11/imm32/alloc-id:fake
28407     _string_0f_87_jump_break/imm32/subx-name
28408     0/imm32/no-rm32
28409     0/imm32/no-r32
28410     0/imm32/no-imm32
28411     0/imm32/no-imm8
28412     0/imm32/no-disp32
28413     0/imm32/no-xm32
28414     0/imm32/no-x32
28415     0x11/imm32/alloc-id:fake
28416     _Primitive-break-if-</imm32/next
28417 _Primitive-break-if-<:  # (payload primitive)
28418     0x11/imm32/alloc-id:fake:payload
28419     0x11/imm32/alloc-id:fake
28420     _string-break-if-</imm32/name
28421     0/imm32/no-inouts
28422     0/imm32/no-inouts
28423     0/imm32/no-outputs
28424     0/imm32/no-outputs
28425     0x11/imm32/alloc-id:fake
28426     _string_0f_8c_jump_break/imm32/subx-name
28427     0/imm32/no-rm32
28428     0/imm32/no-r32
28429     0/imm32/no-imm32
28430     0/imm32/no-imm8
28431     0/imm32/no-disp32
28432     0/imm32/no-xm32
28433     0/imm32/no-x32
28434     0x11/imm32/alloc-id:fake
28435     _Primitive-break-if->=/imm32/next
28436 _Primitive-break-if->=:  # (payload primitive)
28437     0x11/imm32/alloc-id:fake:payload
28438     0x11/imm32/alloc-id:fake
28439     _string-break-if->=/imm32/name
28440     0/imm32/no-inouts
28441     0/imm32/no-inouts
28442     0/imm32/no-outputs
28443     0/imm32/no-outputs
28444     0x11/imm32/alloc-id:fake
28445     _string_0f_8d_jump_break/imm32/subx-name
28446     0/imm32/no-rm32
28447     0/imm32/no-r32
28448     0/imm32/no-imm32
28449     0/imm32/no-imm8
28450     0/imm32/no-disp32
28451     0/imm32/no-xm32
28452     0/imm32/no-x32
28453     0x11/imm32/alloc-id:fake
28454     _Primitive-break-if-<=/imm32/next
28455 _Primitive-break-if-<=:  # (payload primitive)
28456     0x11/imm32/alloc-id:fake:payload
28457     0x11/imm32/alloc-id:fake
28458     _string-break-if-<=/imm32/name
28459     0/imm32/no-inouts
28460     0/imm32/no-inouts
28461     0/imm32/no-outputs
28462     0/imm32/no-outputs
28463     0x11/imm32/alloc-id:fake
28464     _string_0f_8e_jump_break/imm32/subx-name
28465     0/imm32/no-rm32
28466     0/imm32/no-r32
28467     0/imm32/no-imm32
28468     0/imm32/no-imm8
28469     0/imm32/no-disp32
28470     0/imm32/no-xm32
28471     0/imm32/no-x32
28472     0x11/imm32/alloc-id:fake
28473     _Primitive-break-if->/imm32/next
28474 _Primitive-break-if->:  # (payload primitive)
28475     0x11/imm32/alloc-id:fake:payload
28476     0x11/imm32/alloc-id:fake
28477     _string-break-if->/imm32/name
28478     0/imm32/no-inouts
28479     0/imm32/no-inouts
28480     0/imm32/no-outputs
28481     0/imm32/no-outputs
28482     0x11/imm32/alloc-id:fake
28483     _string_0f_8f_jump_break/imm32/subx-name
28484     0/imm32/no-rm32
28485     0/imm32/no-r32
28486     0/imm32/no-imm32
28487     0/imm32/no-imm8
28488     0/imm32/no-disp32
28489     0/imm32/no-xm32
28490     0/imm32/no-x32
28491     0x11/imm32/alloc-id:fake
28492     _Primitive-break/imm32/next
28493 _Primitive-break:  # (payload primitive)
28494     0x11/imm32/alloc-id:fake:payload
28495     0x11/imm32/alloc-id:fake
28496     _string-break/imm32/name
28497     0/imm32/no-inouts
28498     0/imm32/no-inouts
28499     0/imm32/no-outputs
28500     0/imm32/no-outputs
28501     0x11/imm32/alloc-id:fake
28502     _string_e9_jump_break/imm32/subx-name
28503     0/imm32/no-rm32
28504     0/imm32/no-r32
28505     0/imm32/no-imm32
28506     0/imm32/no-imm8
28507     0/imm32/no-disp32
28508     0/imm32/no-xm32
28509     0/imm32/no-x32
28510     0x11/imm32/alloc-id:fake
28511     _Primitive-loop-if-addr</imm32/next
28512 _Primitive-loop-if-addr<:  # (payload primitive)
28513     0x11/imm32/alloc-id:fake:payload
28514     0x11/imm32/alloc-id:fake
28515     _string-loop-if-addr</imm32/name
28516     0/imm32/no-inouts
28517     0/imm32/no-inouts
28518     0/imm32/no-outputs
28519     0/imm32/no-outputs
28520     0x11/imm32/alloc-id:fake
28521     _string_0f_82_jump_loop/imm32/subx-name
28522     0/imm32/no-rm32
28523     0/imm32/no-r32
28524     0/imm32/no-imm32
28525     0/imm32/no-imm8
28526     0/imm32/no-disp32
28527     0/imm32/no-xm32
28528     0/imm32/no-x32
28529     0x11/imm32/alloc-id:fake
28530     _Primitive-loop-if-addr>=/imm32/next
28531 _Primitive-loop-if-addr>=:  # (payload primitive)
28532     0x11/imm32/alloc-id:fake:payload
28533     0x11/imm32/alloc-id:fake
28534     _string-loop-if-addr>=/imm32/name
28535     0/imm32/no-inouts
28536     0/imm32/no-inouts
28537     0/imm32/no-outputs
28538     0/imm32/no-outputs
28539     0x11/imm32/alloc-id:fake
28540     _string_0f_83_jump_loop/imm32/subx-name
28541     0/imm32/no-rm32
28542     0/imm32/no-r32
28543     0/imm32/no-imm32
28544     0/imm32/no-imm8
28545     0/imm32/no-disp32
28546     0/imm32/no-xm32
28547     0/imm32/no-x32
28548     0x11/imm32/alloc-id:fake
28549     _Primitive-loop-if-=/imm32/next
28550 _Primitive-loop-if-=:  # (payload primitive)
28551     0x11/imm32/alloc-id:fake:payload
28552     0x11/imm32/alloc-id:fake
28553     _string-loop-if-=/imm32/name
28554     0/imm32/no-inouts
28555     0/imm32/no-inouts
28556     0/imm32/no-outputs
28557     0/imm32/no-outputs
28558     0x11/imm32/alloc-id:fake
28559     _string_0f_84_jump_loop/imm32/subx-name
28560     0/imm32/no-rm32
28561     0/imm32/no-r32
28562     0/imm32/no-imm32
28563     0/imm32/no-imm8
28564     0/imm32/no-disp32
28565     0/imm32/no-xm32
28566     0/imm32/no-x32
28567     0x11/imm32/alloc-id:fake
28568     _Primitive-loop-if-!=/imm32/next
28569 _Primitive-loop-if-!=:  # (payload primitive)
28570     0x11/imm32/alloc-id:fake:payload
28571     0x11/imm32/alloc-id:fake
28572     _string-loop-if-!=/imm32/name
28573     0/imm32/no-inouts
28574     0/imm32/no-inouts
28575     0/imm32/no-outputs
28576     0/imm32/no-outputs
28577     0x11/imm32/alloc-id:fake
28578     _string_0f_85_jump_loop/imm32/subx-name
28579     0/imm32/no-rm32
28580     0/imm32/no-r32
28581     0/imm32/no-imm32
28582     0/imm32/no-imm8
28583     0/imm32/no-disp32
28584     0/imm32/no-xm32
28585     0/imm32/no-x32
28586     0x11/imm32/alloc-id:fake
28587     _Primitive-loop-if-addr<=/imm32/next
28588 _Primitive-loop-if-addr<=:  # (payload primitive)
28589     0x11/imm32/alloc-id:fake:payload
28590     0x11/imm32/alloc-id:fake
28591     _string-loop-if-addr<=/imm32/name
28592     0/imm32/no-inouts
28593     0/imm32/no-inouts
28594     0/imm32/no-outputs
28595     0/imm32/no-outputs
28596     0x11/imm32/alloc-id:fake
28597     _string_0f_86_jump_loop/imm32/subx-name
28598     0/imm32/no-rm32
28599     0/imm32/no-r32
28600     0/imm32/no-imm32
28601     0/imm32/no-imm8
28602     0/imm32/no-disp32
28603     0/imm32/no-xm32
28604     0/imm32/no-x32
28605     0x11/imm32/alloc-id:fake
28606     _Primitive-loop-if-addr>/imm32/next
28607 _Primitive-loop-if-addr>:  # (payload primitive)
28608     0x11/imm32/alloc-id:fake:payload
28609     0x11/imm32/alloc-id:fake
28610     _string-loop-if-addr>/imm32/name
28611     0/imm32/no-inouts
28612     0/imm32/no-inouts
28613     0/imm32/no-outputs
28614     0/imm32/no-outputs
28615     0x11/imm32/alloc-id:fake
28616     _string_0f_87_jump_loop/imm32/subx-name
28617     0/imm32/no-rm32
28618     0/imm32/no-r32
28619     0/imm32/no-imm32
28620     0/imm32/no-imm8
28621     0/imm32/no-disp32
28622     0/imm32/no-xm32
28623     0/imm32/no-x32
28624     0x11/imm32/alloc-id:fake
28625     _Primitive-loop-if-</imm32/next
28626 _Primitive-loop-if-<:  # (payload primitive)
28627     0x11/imm32/alloc-id:fake:payload
28628     0x11/imm32/alloc-id:fake
28629     _string-loop-if-</imm32/name
28630     0/imm32/no-inouts
28631     0/imm32/no-inouts
28632     0/imm32/no-outputs
28633     0/imm32/no-outputs
28634     0x11/imm32/alloc-id:fake
28635     _string_0f_8c_jump_loop/imm32/subx-name
28636     0/imm32/no-rm32
28637     0/imm32/no-r32
28638     0/imm32/no-imm32
28639     0/imm32/no-imm8
28640     0/imm32/no-disp32
28641     0/imm32/no-xm32
28642     0/imm32/no-x32
28643     0x11/imm32/alloc-id:fake
28644     _Primitive-loop-if->=/imm32/next
28645 _Primitive-loop-if->=:  # (payload primitive)
28646     0x11/imm32/alloc-id:fake:payload
28647     0x11/imm32/alloc-id:fake
28648     _string-loop-if->=/imm32/name
28649     0/imm32/no-inouts
28650     0/imm32/no-inouts
28651     0/imm32/no-outputs
28652     0/imm32/no-outputs
28653     0x11/imm32/alloc-id:fake
28654     _string_0f_8d_jump_loop/imm32/subx-name
28655     0/imm32/no-rm32
28656     0/imm32/no-r32
28657     0/imm32/no-imm32
28658     0/imm32/no-imm8
28659     0/imm32/no-disp32
28660     0/imm32/no-xm32
28661     0/imm32/no-x32
28662     0x11/imm32/alloc-id:fake
28663     _Primitive-loop-if-<=/imm32/next
28664 _Primitive-loop-if-<=:  # (payload primitive)
28665     0x11/imm32/alloc-id:fake:payload
28666     0x11/imm32/alloc-id:fake
28667     _string-loop-if-<=/imm32/name
28668     0/imm32/no-inouts
28669     0/imm32/no-inouts
28670     0/imm32/no-outputs
28671     0/imm32/no-outputs
28672     0x11/imm32/alloc-id:fake
28673     _string_0f_8e_jump_loop/imm32/subx-name
28674     0/imm32/no-rm32
28675     0/imm32/no-r32
28676     0/imm32/no-imm32
28677     0/imm32/no-imm8
28678     0/imm32/no-disp32
28679     0/imm32/no-xm32
28680     0/imm32/no-x32
28681     0x11/imm32/alloc-id:fake
28682     _Primitive-loop-if->/imm32/next
28683 _Primitive-loop-if->:  # (payload primitive)
28684     0x11/imm32/alloc-id:fake:payload
28685     0x11/imm32/alloc-id:fake
28686     _string-loop-if->/imm32/name
28687     0/imm32/no-inouts
28688     0/imm32/no-inouts
28689     0/imm32/no-outputs
28690     0/imm32/no-outputs
28691     0x11/imm32/alloc-id:fake
28692     _string_0f_8f_jump_loop/imm32/subx-name
28693     0/imm32/no-rm32
28694     0/imm32/no-r32
28695     0/imm32/no-imm32
28696     0/imm32/no-imm8
28697     0/imm32/no-disp32
28698     0/imm32/no-xm32
28699     0/imm32/no-x32
28700     0x11/imm32/alloc-id:fake
28701     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
28702 _Primitive-loop:  # (payload primitive)
28703     0x11/imm32/alloc-id:fake:payload
28704     0x11/imm32/alloc-id:fake
28705     _string-loop/imm32/name
28706     0/imm32/no-inouts
28707     0/imm32/no-inouts
28708     0/imm32/no-outputs
28709     0/imm32/no-outputs
28710     0x11/imm32/alloc-id:fake
28711     _string_e9_jump_loop/imm32/subx-name
28712     0/imm32/no-rm32
28713     0/imm32/no-r32
28714     0/imm32/no-imm32
28715     0/imm32/no-imm8
28716     0/imm32/no-disp32
28717     0/imm32/no-xm32
28718     0/imm32/no-x32
28719     0x11/imm32/alloc-id:fake
28720     _Primitive-break-if-addr<-named/imm32/next
28721 # - branches to named blocks
28722 _Primitive-break-if-addr<-named:  # (payload primitive)
28723     0x11/imm32/alloc-id:fake:payload
28724     0x11/imm32/alloc-id:fake
28725     _string-break-if-addr</imm32/name
28726     0x11/imm32/alloc-id:fake
28727     Single-lit-var/imm32/inouts
28728     0/imm32/no-outputs
28729     0/imm32/no-outputs
28730     0x11/imm32/alloc-id:fake
28731     _string_0f_82_jump_label/imm32/subx-name
28732     0/imm32/no-rm32
28733     0/imm32/no-r32
28734     0/imm32/no-imm32
28735     0/imm32/no-imm8
28736     1/imm32/disp32-is-first-inout
28737     0/imm32/no-xm32
28738     0/imm32/no-x32
28739     0x11/imm32/alloc-id:fake
28740     _Primitive-break-if-addr>=-named/imm32/next
28741 _Primitive-break-if-addr>=-named:  # (payload primitive)
28742     0x11/imm32/alloc-id:fake:payload
28743     0x11/imm32/alloc-id:fake
28744     _string-break-if-addr>=/imm32/name
28745     0x11/imm32/alloc-id:fake
28746     Single-lit-var/imm32/inouts
28747     0/imm32/no-outputs
28748     0/imm32/no-outputs
28749     0x11/imm32/alloc-id:fake
28750     _string_0f_83_jump_label/imm32/subx-name
28751     0/imm32/no-rm32
28752     0/imm32/no-r32
28753     0/imm32/no-imm32
28754     0/imm32/no-imm8
28755     1/imm32/disp32-is-first-inout
28756     0/imm32/no-xm32
28757     0/imm32/no-x32
28758     0x11/imm32/alloc-id:fake
28759     _Primitive-break-if-=-named/imm32/next
28760 _Primitive-break-if-=-named:  # (payload primitive)
28761     0x11/imm32/alloc-id:fake:payload
28762     0x11/imm32/alloc-id:fake
28763     _string-break-if-=/imm32/name
28764     0x11/imm32/alloc-id:fake
28765     Single-lit-var/imm32/inouts
28766     0/imm32/no-outputs
28767     0/imm32/no-outputs
28768     0x11/imm32/alloc-id:fake
28769     _string_0f_84_jump_label/imm32/subx-name
28770     0/imm32/no-rm32
28771     0/imm32/no-r32
28772     0/imm32/no-imm32
28773     0/imm32/no-imm8
28774     1/imm32/disp32-is-first-inout
28775     0/imm32/no-xm32
28776     0/imm32/no-x32
28777     0x11/imm32/alloc-id:fake
28778     _Primitive-break-if-!=-named/imm32/next
28779 _Primitive-break-if-!=-named:  # (payload primitive)
28780     0x11/imm32/alloc-id:fake:payload
28781     0x11/imm32/alloc-id:fake
28782     _string-break-if-!=/imm32/name
28783     0x11/imm32/alloc-id:fake
28784     Single-lit-var/imm32/inouts
28785     0/imm32/no-outputs
28786     0/imm32/no-outputs
28787     0x11/imm32/alloc-id:fake
28788     _string_0f_85_jump_label/imm32/subx-name
28789     0/imm32/no-rm32
28790     0/imm32/no-r32
28791     0/imm32/no-imm32
28792     0/imm32/no-imm8
28793     1/imm32/disp32-is-first-inout
28794     0/imm32/no-xm32
28795     0/imm32/no-x32
28796     0x11/imm32/alloc-id:fake
28797     _Primitive-break-if-addr<=-named/imm32/next
28798 _Primitive-break-if-addr<=-named:  # (payload primitive)
28799     0x11/imm32/alloc-id:fake:payload
28800     0x11/imm32/alloc-id:fake
28801     _string-break-if-addr<=/imm32/name
28802     0x11/imm32/alloc-id:fake
28803     Single-lit-var/imm32/inouts
28804     0/imm32/no-outputs
28805     0/imm32/no-outputs
28806     0x11/imm32/alloc-id:fake
28807     _string_0f_86_jump_label/imm32/subx-name
28808     0/imm32/no-rm32
28809     0/imm32/no-r32
28810     0/imm32/no-imm32
28811     0/imm32/no-imm8
28812     1/imm32/disp32-is-first-inout
28813     0/imm32/no-xm32
28814     0/imm32/no-x32
28815     0x11/imm32/alloc-id:fake
28816     _Primitive-break-if-addr>-named/imm32/next
28817 _Primitive-break-if-addr>-named:  # (payload primitive)
28818     0x11/imm32/alloc-id:fake:payload
28819     0x11/imm32/alloc-id:fake
28820     _string-break-if-addr>/imm32/name
28821     0x11/imm32/alloc-id:fake
28822     Single-lit-var/imm32/inouts
28823     0/imm32/no-outputs
28824     0/imm32/no-outputs
28825     0x11/imm32/alloc-id:fake
28826     _string_0f_87_jump_label/imm32/subx-name
28827     0/imm32/no-rm32
28828     0/imm32/no-r32
28829     0/imm32/no-imm32
28830     0/imm32/no-imm8
28831     1/imm32/disp32-is-first-inout
28832     0/imm32/no-xm32
28833     0/imm32/no-x32
28834     0x11/imm32/alloc-id:fake
28835     _Primitive-break-if-<-named/imm32/next
28836 _Primitive-break-if-<-named:  # (payload primitive)
28837     0x11/imm32/alloc-id:fake:payload
28838     0x11/imm32/alloc-id:fake
28839     _string-break-if-</imm32/name
28840     0x11/imm32/alloc-id:fake
28841     Single-lit-var/imm32/inouts
28842     0/imm32/no-outputs
28843     0/imm32/no-outputs
28844     0x11/imm32/alloc-id:fake
28845     _string_0f_8c_jump_label/imm32/subx-name
28846     0/imm32/no-rm32
28847     0/imm32/no-r32
28848     0/imm32/no-imm32
28849     0/imm32/no-imm8
28850     1/imm32/disp32-is-first-inout
28851     0/imm32/no-xm32
28852     0/imm32/no-x32
28853     0x11/imm32/alloc-id:fake
28854     _Primitive-break-if->=-named/imm32/next
28855 _Primitive-break-if->=-named:  # (payload primitive)
28856     0x11/imm32/alloc-id:fake:payload
28857     0x11/imm32/alloc-id:fake
28858     _string-break-if->=/imm32/name
28859     0x11/imm32/alloc-id:fake
28860     Single-lit-var/imm32/inouts
28861     0/imm32/no-outputs
28862     0/imm32/no-outputs
28863     0x11/imm32/alloc-id:fake
28864     _string_0f_8d_jump_label/imm32/subx-name
28865     0/imm32/no-rm32
28866     0/imm32/no-r32
28867     0/imm32/no-imm32
28868     0/imm32/no-imm8
28869     1/imm32/disp32-is-first-inout
28870     0/imm32/no-xm32
28871     0/imm32/no-x32
28872     0x11/imm32/alloc-id:fake
28873     _Primitive-break-if-<=-named/imm32/next
28874 _Primitive-break-if-<=-named:  # (payload primitive)
28875     0x11/imm32/alloc-id:fake:payload
28876     0x11/imm32/alloc-id:fake
28877     _string-break-if-<=/imm32/name
28878     0x11/imm32/alloc-id:fake
28879     Single-lit-var/imm32/inouts
28880     0/imm32/no-outputs
28881     0/imm32/no-outputs
28882     0x11/imm32/alloc-id:fake
28883     _string_0f_8e_jump_label/imm32/subx-name
28884     0/imm32/no-rm32
28885     0/imm32/no-r32
28886     0/imm32/no-imm32
28887     0/imm32/no-imm8
28888     1/imm32/disp32-is-first-inout
28889     0/imm32/no-xm32
28890     0/imm32/no-x32
28891     0x11/imm32/alloc-id:fake
28892     _Primitive-break-if->-named/imm32/next
28893 _Primitive-break-if->-named:  # (payload primitive)
28894     0x11/imm32/alloc-id:fake:payload
28895     0x11/imm32/alloc-id:fake
28896     _string-break-if->/imm32/name
28897     0x11/imm32/alloc-id:fake
28898     Single-lit-var/imm32/inouts
28899     0/imm32/no-outputs
28900     0/imm32/no-outputs
28901     0x11/imm32/alloc-id:fake
28902     _string_0f_8f_jump_label/imm32/subx-name
28903     0/imm32/no-rm32
28904     0/imm32/no-r32
28905     0/imm32/no-imm32
28906     0/imm32/no-imm8
28907     1/imm32/disp32-is-first-inout
28908     0/imm32/no-xm32
28909     0/imm32/no-x32
28910     0x11/imm32/alloc-id:fake
28911     _Primitive-break-named/imm32/next
28912 _Primitive-break-named:  # (payload primitive)
28913     0x11/imm32/alloc-id:fake:payload
28914     0x11/imm32/alloc-id:fake
28915     _string-break/imm32/name
28916     0x11/imm32/alloc-id:fake
28917     Single-lit-var/imm32/inouts
28918     0/imm32/no-outputs
28919     0/imm32/no-outputs
28920     0x11/imm32/alloc-id:fake
28921     _string_e9_jump_label/imm32/subx-name
28922     0/imm32/no-rm32
28923     0/imm32/no-r32
28924     0/imm32/no-imm32
28925     0/imm32/no-imm8
28926     1/imm32/disp32-is-first-inout
28927     0/imm32/no-xm32
28928     0/imm32/no-x32
28929     0x11/imm32/alloc-id:fake
28930     _Primitive-loop-if-addr<-named/imm32/next
28931 _Primitive-loop-if-addr<-named:  # (payload primitive)
28932     0x11/imm32/alloc-id:fake:payload
28933     0x11/imm32/alloc-id:fake
28934     _string-loop-if-addr</imm32/name
28935     0x11/imm32/alloc-id:fake
28936     Single-lit-var/imm32/inouts
28937     0/imm32/no-outputs
28938     0/imm32/no-outputs
28939     0x11/imm32/alloc-id:fake
28940     _string_0f_82_jump_label/imm32/subx-name
28941     0/imm32/no-rm32
28942     0/imm32/no-r32
28943     0/imm32/no-imm32
28944     0/imm32/no-imm8
28945     1/imm32/disp32-is-first-inout
28946     0/imm32/no-xm32
28947     0/imm32/no-x32
28948     0x11/imm32/alloc-id:fake
28949     _Primitive-loop-if-addr>=-named/imm32/next
28950 _Primitive-loop-if-addr>=-named:  # (payload primitive)
28951     0x11/imm32/alloc-id:fake:payload
28952     0x11/imm32/alloc-id:fake
28953     _string-loop-if-addr>=/imm32/name
28954     0x11/imm32/alloc-id:fake
28955     Single-lit-var/imm32/inouts
28956     0/imm32/no-outputs
28957     0/imm32/no-outputs
28958     0x11/imm32/alloc-id:fake
28959     _string_0f_83_jump_label/imm32/subx-name
28960     0/imm32/no-rm32
28961     0/imm32/no-r32
28962     0/imm32/no-imm32
28963     0/imm32/no-imm8
28964     1/imm32/disp32-is-first-inout
28965     0/imm32/no-xm32
28966     0/imm32/no-x32
28967     0x11/imm32/alloc-id:fake
28968     _Primitive-loop-if-=-named/imm32/next
28969 _Primitive-loop-if-=-named:  # (payload primitive)
28970     0x11/imm32/alloc-id:fake:payload
28971     0x11/imm32/alloc-id:fake
28972     _string-loop-if-=/imm32/name
28973     0x11/imm32/alloc-id:fake
28974     Single-lit-var/imm32/inouts
28975     0/imm32/no-outputs
28976     0/imm32/no-outputs
28977     0x11/imm32/alloc-id:fake
28978     _string_0f_84_jump_label/imm32/subx-name
28979     0/imm32/no-rm32
28980     0/imm32/no-r32
28981     0/imm32/no-imm32
28982     0/imm32/no-imm8
28983     1/imm32/disp32-is-first-inout
28984     0/imm32/no-xm32
28985     0/imm32/no-x32
28986     0x11/imm32/alloc-id:fake
28987     _Primitive-loop-if-!=-named/imm32/next
28988 _Primitive-loop-if-!=-named:  # (payload primitive)
28989     0x11/imm32/alloc-id:fake:payload
28990     0x11/imm32/alloc-id:fake
28991     _string-loop-if-!=/imm32/name
28992     0x11/imm32/alloc-id:fake
28993     Single-lit-var/imm32/inouts
28994     0/imm32/no-outputs
28995     0/imm32/no-outputs
28996     0x11/imm32/alloc-id:fake
28997     _string_0f_85_jump_label/imm32/subx-name
28998     0/imm32/no-rm32
28999     0/imm32/no-r32
29000     0/imm32/no-imm32
29001     0/imm32/no-imm8
29002     1/imm32/disp32-is-first-inout
29003     0/imm32/no-xm32
29004     0/imm32/no-x32
29005     0x11/imm32/alloc-id:fake
29006     _Primitive-loop-if-addr<=-named/imm32/next
29007 _Primitive-loop-if-addr<=-named:  # (payload primitive)
29008     0x11/imm32/alloc-id:fake:payload
29009     0x11/imm32/alloc-id:fake
29010     _string-loop-if-addr<=/imm32/name
29011     0x11/imm32/alloc-id:fake
29012     Single-lit-var/imm32/inouts
29013     0/imm32/no-outputs
29014     0/imm32/no-outputs
29015     0x11/imm32/alloc-id:fake
29016     _string_0f_86_jump_label/imm32/subx-name
29017     0/imm32/no-rm32
29018     0/imm32/no-r32
29019     0/imm32/no-imm32
29020     0/imm32/no-imm8
29021     1/imm32/disp32-is-first-inout
29022     0/imm32/no-xm32
29023     0/imm32/no-x32
29024     0x11/imm32/alloc-id:fake
29025     _Primitive-loop-if-addr>-named/imm32/next
29026 _Primitive-loop-if-addr>-named:  # (payload primitive)
29027     0x11/imm32/alloc-id:fake:payload
29028     0x11/imm32/alloc-id:fake
29029     _string-loop-if-addr>/imm32/name
29030     0x11/imm32/alloc-id:fake
29031     Single-lit-var/imm32/inouts
29032     0/imm32/no-outputs
29033     0/imm32/no-outputs
29034     0x11/imm32/alloc-id:fake
29035     _string_0f_87_jump_label/imm32/subx-name
29036     0/imm32/no-rm32
29037     0/imm32/no-r32
29038     0/imm32/no-imm32
29039     0/imm32/no-imm8
29040     1/imm32/disp32-is-first-inout
29041     0/imm32/no-xm32
29042     0/imm32/no-x32
29043     0x11/imm32/alloc-id:fake
29044     _Primitive-loop-if-<-named/imm32/next
29045 _Primitive-loop-if-<-named:  # (payload primitive)
29046     0x11/imm32/alloc-id:fake:payload
29047     0x11/imm32/alloc-id:fake
29048     _string-loop-if-</imm32/name
29049     0x11/imm32/alloc-id:fake
29050     Single-lit-var/imm32/inouts
29051     0/imm32/no-outputs
29052     0/imm32/no-outputs
29053     0x11/imm32/alloc-id:fake
29054     _string_0f_8c_jump_label/imm32/subx-name
29055     0/imm32/no-rm32
29056     0/imm32/no-r32
29057     0/imm32/no-imm32
29058     0/imm32/no-imm8
29059     1/imm32/disp32-is-first-inout
29060     0/imm32/no-xm32
29061     0/imm32/no-x32
29062     0x11/imm32/alloc-id:fake
29063     _Primitive-loop-if->=-named/imm32/next
29064 _Primitive-loop-if->=-named:  # (payload primitive)
29065     0x11/imm32/alloc-id:fake:payload
29066     0x11/imm32/alloc-id:fake
29067     _string-loop-if->=/imm32/name
29068     0x11/imm32/alloc-id:fake
29069     Single-lit-var/imm32/inouts
29070     0/imm32/no-outputs
29071     0/imm32/no-outputs
29072     0x11/imm32/alloc-id:fake
29073     _string_0f_8d_jump_label/imm32/subx-name
29074     0/imm32/no-rm32
29075     0/imm32/no-r32
29076     0/imm32/no-imm32
29077     0/imm32/no-imm8
29078     1/imm32/disp32-is-first-inout
29079     0/imm32/no-xm32
29080     0/imm32/no-x32
29081     0x11/imm32/alloc-id:fake
29082     _Primitive-loop-if-<=-named/imm32/next
29083 _Primitive-loop-if-<=-named:  # (payload primitive)
29084     0x11/imm32/alloc-id:fake:payload
29085     0x11/imm32/alloc-id:fake
29086     _string-loop-if-<=/imm32/name
29087     0x11/imm32/alloc-id:fake
29088     Single-lit-var/imm32/inouts
29089     0/imm32/no-outputs
29090     0/imm32/no-outputs
29091     0x11/imm32/alloc-id:fake
29092     _string_0f_8e_jump_label/imm32/subx-name
29093     0/imm32/no-rm32
29094     0/imm32/no-r32
29095     0/imm32/no-imm32
29096     0/imm32/no-imm8
29097     1/imm32/disp32-is-first-inout
29098     0/imm32/no-xm32
29099     0/imm32/no-x32
29100     0x11/imm32/alloc-id:fake
29101     _Primitive-loop-if->-named/imm32/next
29102 _Primitive-loop-if->-named:  # (payload primitive)
29103     0x11/imm32/alloc-id:fake:payload
29104     0x11/imm32/alloc-id:fake
29105     _string-loop-if->/imm32/name
29106     0x11/imm32/alloc-id:fake
29107     Single-lit-var/imm32/inouts
29108     0/imm32/no-outputs
29109     0/imm32/no-outputs
29110     0x11/imm32/alloc-id:fake
29111     _string_0f_8f_jump_label/imm32/subx-name
29112     0/imm32/no-rm32
29113     0/imm32/no-r32
29114     0/imm32/no-imm32
29115     0/imm32/no-imm8
29116     1/imm32/disp32-is-first-inout
29117     0/imm32/no-xm32
29118     0/imm32/no-x32
29119     0x11/imm32/alloc-id:fake
29120     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
29121 _Primitive-loop-named:  # (payload primitive)
29122     0x11/imm32/alloc-id:fake:payload
29123     0x11/imm32/alloc-id:fake
29124     _string-loop/imm32/name
29125     0x11/imm32/alloc-id:fake
29126     Single-lit-var/imm32/inouts
29127     0/imm32/no-outputs
29128     0/imm32/no-outputs
29129     0x11/imm32/alloc-id:fake
29130     _string_e9_jump_label/imm32/subx-name
29131     0/imm32/no-rm32
29132     0/imm32/no-r32
29133     0/imm32/no-imm32
29134     0/imm32/no-imm8
29135     1/imm32/disp32-is-first-inout
29136     0/imm32/no-xm32
29137     0/imm32/no-x32
29138     0x11/imm32/alloc-id:fake
29139     _Primitive-break-if-float</imm32/next
29140 # - branches based on floating-point comparisons
29141 _Primitive-break-if-float<:  # (payload primitive)
29142     0x11/imm32/alloc-id:fake:payload
29143     0x11/imm32/alloc-id:fake
29144     _string-break-if-float</imm32/name
29145     0/imm32/no-inouts
29146     0/imm32/no-inouts
29147     0/imm32/no-outputs
29148     0/imm32/no-outputs
29149     0x11/imm32/alloc-id:fake
29150     _string_0f_82_jump_break/imm32/subx-name
29151     0/imm32/no-rm32
29152     0/imm32/no-r32
29153     0/imm32/no-imm32
29154     0/imm32/no-imm8
29155     0/imm32/no-disp32
29156     0/imm32/no-xm32
29157     0/imm32/no-x32
29158     0x11/imm32/alloc-id:fake
29159     _Primitive-break-if-float>=/imm32/next
29160 _Primitive-break-if-float>=:  # (payload primitive)
29161     0x11/imm32/alloc-id:fake:payload
29162     0x11/imm32/alloc-id:fake
29163     _string-break-if-float>=/imm32/name
29164     0/imm32/no-inouts
29165     0/imm32/no-inouts
29166     0/imm32/no-outputs
29167     0/imm32/no-outputs
29168     0x11/imm32/alloc-id:fake
29169     _string_0f_83_jump_break/imm32/subx-name
29170     0/imm32/no-rm32
29171     0/imm32/no-r32
29172     0/imm32/no-imm32
29173     0/imm32/no-imm8
29174     0/imm32/no-disp32
29175     0/imm32/no-xm32
29176     0/imm32/no-x32
29177     0x11/imm32/alloc-id:fake
29178     _Primitive-break-if-float<=/imm32/next
29179 _Primitive-break-if-float<=:  # (payload primitive)
29180     0x11/imm32/alloc-id:fake:payload
29181     0x11/imm32/alloc-id:fake
29182     _string-break-if-float<=/imm32/name
29183     0/imm32/no-inouts
29184     0/imm32/no-inouts
29185     0/imm32/no-outputs
29186     0/imm32/no-outputs
29187     0x11/imm32/alloc-id:fake
29188     _string_0f_86_jump_break/imm32/subx-name
29189     0/imm32/no-rm32
29190     0/imm32/no-r32
29191     0/imm32/no-imm32
29192     0/imm32/no-imm8
29193     0/imm32/no-disp32
29194     0/imm32/no-xm32
29195     0/imm32/no-x32
29196     0x11/imm32/alloc-id:fake
29197     _Primitive-break-if-float>/imm32/next
29198 _Primitive-break-if-float>:  # (payload primitive)
29199     0x11/imm32/alloc-id:fake:payload
29200     0x11/imm32/alloc-id:fake
29201     _string-break-if-float>/imm32/name
29202     0/imm32/no-inouts
29203     0/imm32/no-inouts
29204     0/imm32/no-outputs
29205     0/imm32/no-outputs
29206     0x11/imm32/alloc-id:fake
29207     _string_0f_87_jump_break/imm32/subx-name
29208     0/imm32/no-rm32
29209     0/imm32/no-r32
29210     0/imm32/no-imm32
29211     0/imm32/no-imm8
29212     0/imm32/no-disp32
29213     0/imm32/no-xm32
29214     0/imm32/no-x32
29215     0x11/imm32/alloc-id:fake
29216     _Primitive-loop-if-float</imm32/next
29217 _Primitive-loop-if-float<:  # (payload primitive)
29218     0x11/imm32/alloc-id:fake:payload
29219     0x11/imm32/alloc-id:fake
29220     _string-loop-if-float</imm32/name
29221     0/imm32/no-inouts
29222     0/imm32/no-inouts
29223     0/imm32/no-outputs
29224     0/imm32/no-outputs
29225     0x11/imm32/alloc-id:fake
29226     _string_0f_82_jump_loop/imm32/subx-name
29227     0/imm32/no-rm32
29228     0/imm32/no-r32
29229     0/imm32/no-imm32
29230     0/imm32/no-imm8
29231     0/imm32/no-disp32
29232     0/imm32/no-xm32
29233     0/imm32/no-x32
29234     0x11/imm32/alloc-id:fake
29235     _Primitive-loop-if-float>=/imm32/next
29236 _Primitive-loop-if-float>=:  # (payload primitive)
29237     0x11/imm32/alloc-id:fake:payload
29238     0x11/imm32/alloc-id:fake
29239     _string-loop-if-float>=/imm32/name
29240     0/imm32/no-inouts
29241     0/imm32/no-inouts
29242     0/imm32/no-outputs
29243     0/imm32/no-outputs
29244     0x11/imm32/alloc-id:fake
29245     _string_0f_83_jump_loop/imm32/subx-name
29246     0/imm32/no-rm32
29247     0/imm32/no-r32
29248     0/imm32/no-imm32
29249     0/imm32/no-imm8
29250     0/imm32/no-disp32
29251     0/imm32/no-xm32
29252     0/imm32/no-x32
29253     0x11/imm32/alloc-id:fake
29254     _Primitive-loop-if-float<=/imm32/next
29255 _Primitive-loop-if-float<=:  # (payload primitive)
29256     0x11/imm32/alloc-id:fake:payload
29257     0x11/imm32/alloc-id:fake
29258     _string-loop-if-float<=/imm32/name
29259     0/imm32/no-inouts
29260     0/imm32/no-inouts
29261     0/imm32/no-outputs
29262     0/imm32/no-outputs
29263     0x11/imm32/alloc-id:fake
29264     _string_0f_86_jump_loop/imm32/subx-name
29265     0/imm32/no-rm32
29266     0/imm32/no-r32
29267     0/imm32/no-imm32
29268     0/imm32/no-imm8
29269     0/imm32/no-disp32
29270     0/imm32/no-xm32
29271     0/imm32/no-x32
29272     0x11/imm32/alloc-id:fake
29273     _Primitive-loop-if-float>/imm32/next
29274 _Primitive-loop-if-float>:  # (payload primitive)
29275     0x11/imm32/alloc-id:fake:payload
29276     0x11/imm32/alloc-id:fake
29277     _string-loop-if-float>/imm32/name
29278     0/imm32/no-inouts
29279     0/imm32/no-inouts
29280     0/imm32/no-outputs
29281     0/imm32/no-outputs
29282     0x11/imm32/alloc-id:fake
29283     _string_0f_87_jump_loop/imm32/subx-name
29284     0/imm32/no-rm32
29285     0/imm32/no-r32
29286     0/imm32/no-imm32
29287     0/imm32/no-imm8
29288     0/imm32/no-disp32
29289     0/imm32/no-xm32
29290     0/imm32/no-x32
29291     0x11/imm32/alloc-id:fake
29292     _Primitive-break-if-float<-named/imm32/next
29293 _Primitive-break-if-float<-named:  # (payload primitive)
29294     0x11/imm32/alloc-id:fake:payload
29295     0x11/imm32/alloc-id:fake
29296     _string-break-if-float</imm32/name
29297     0x11/imm32/alloc-id:fake
29298     Single-lit-var/imm32/inouts
29299     0/imm32/no-outputs
29300     0/imm32/no-outputs
29301     0x11/imm32/alloc-id:fake
29302     _string_0f_82_jump_label/imm32/subx-name
29303     0/imm32/no-rm32
29304     0/imm32/no-r32
29305     0/imm32/no-imm32
29306     0/imm32/no-imm8
29307     1/imm32/disp32-is-first-inout
29308     0/imm32/no-xm32
29309     0/imm32/no-x32
29310     0x11/imm32/alloc-id:fake
29311     _Primitive-break-if-float>=-named/imm32/next
29312 _Primitive-break-if-float>=-named:  # (payload primitive)
29313     0x11/imm32/alloc-id:fake:payload
29314     0x11/imm32/alloc-id:fake
29315     _string-break-if-float>=/imm32/name
29316     0x11/imm32/alloc-id:fake
29317     Single-lit-var/imm32/inouts
29318     0/imm32/no-outputs
29319     0/imm32/no-outputs
29320     0x11/imm32/alloc-id:fake
29321     _string_0f_83_jump_label/imm32/subx-name
29322     0/imm32/no-rm32
29323     0/imm32/no-r32
29324     0/imm32/no-imm32
29325     0/imm32/no-imm8
29326     1/imm32/disp32-is-first-inout
29327     0/imm32/no-xm32
29328     0/imm32/no-x32
29329     0x11/imm32/alloc-id:fake
29330     _Primitive-break-if-float<=-named/imm32/next
29331 _Primitive-break-if-float<=-named:  # (payload primitive)
29332     0x11/imm32/alloc-id:fake:payload
29333     0x11/imm32/alloc-id:fake
29334     _string-break-if-float<=/imm32/name
29335     0x11/imm32/alloc-id:fake
29336     Single-lit-var/imm32/inouts
29337     0/imm32/no-outputs
29338     0/imm32/no-outputs
29339     0x11/imm32/alloc-id:fake
29340     _string_0f_86_jump_label/imm32/subx-name
29341     0/imm32/no-rm32
29342     0/imm32/no-r32
29343     0/imm32/no-imm32
29344     0/imm32/no-imm8
29345     1/imm32/disp32-is-first-inout
29346     0/imm32/no-xm32
29347     0/imm32/no-x32
29348     0x11/imm32/alloc-id:fake
29349     _Primitive-break-if-float>-named/imm32/next
29350 _Primitive-break-if-float>-named:  # (payload primitive)
29351     0x11/imm32/alloc-id:fake:payload
29352     0x11/imm32/alloc-id:fake
29353     _string-break-if-float>/imm32/name
29354     0x11/imm32/alloc-id:fake
29355     Single-lit-var/imm32/inouts
29356     0/imm32/no-outputs
29357     0/imm32/no-outputs
29358     0x11/imm32/alloc-id:fake
29359     _string_0f_87_jump_label/imm32/subx-name
29360     0/imm32/no-rm32
29361     0/imm32/no-r32
29362     0/imm32/no-imm32
29363     0/imm32/no-imm8
29364     1/imm32/disp32-is-first-inout
29365     0/imm32/no-xm32
29366     0/imm32/no-x32
29367     0x11/imm32/alloc-id:fake
29368     _Primitive-loop-if-float<-named/imm32/next
29369 _Primitive-loop-if-float<-named:  # (payload primitive)
29370     0x11/imm32/alloc-id:fake:payload
29371     0x11/imm32/alloc-id:fake
29372     _string-loop-if-float</imm32/name
29373     0x11/imm32/alloc-id:fake
29374     Single-lit-var/imm32/inouts
29375     0/imm32/no-outputs
29376     0/imm32/no-outputs
29377     0x11/imm32/alloc-id:fake
29378     _string_0f_82_jump_label/imm32/subx-name
29379     0/imm32/no-rm32
29380     0/imm32/no-r32
29381     0/imm32/no-imm32
29382     0/imm32/no-imm8
29383     1/imm32/disp32-is-first-inout
29384     0/imm32/no-xm32
29385     0/imm32/no-x32
29386     0x11/imm32/alloc-id:fake
29387     _Primitive-loop-if-float>=-named/imm32/next
29388 _Primitive-loop-if-float>=-named:  # (payload primitive)
29389     0x11/imm32/alloc-id:fake:payload
29390     0x11/imm32/alloc-id:fake
29391     _string-loop-if-float>=/imm32/name
29392     0x11/imm32/alloc-id:fake
29393     Single-lit-var/imm32/inouts
29394     0/imm32/no-outputs
29395     0/imm32/no-outputs
29396     0x11/imm32/alloc-id:fake
29397     _string_0f_83_jump_label/imm32/subx-name
29398     0/imm32/no-rm32
29399     0/imm32/no-r32
29400     0/imm32/no-imm32
29401     0/imm32/no-imm8
29402     1/imm32/disp32-is-first-inout
29403     0/imm32/no-xm32
29404     0/imm32/no-x32
29405     0x11/imm32/alloc-id:fake
29406     _Primitive-loop-if-float<=-named/imm32/next
29407 _Primitive-loop-if-float<=-named:  # (payload primitive)
29408     0x11/imm32/alloc-id:fake:payload
29409     0x11/imm32/alloc-id:fake
29410     _string-loop-if-float<=/imm32/name
29411     0x11/imm32/alloc-id:fake
29412     Single-lit-var/imm32/inouts
29413     0/imm32/no-outputs
29414     0/imm32/no-outputs
29415     0x11/imm32/alloc-id:fake
29416     _string_0f_86_jump_label/imm32/subx-name
29417     0/imm32/no-rm32
29418     0/imm32/no-r32
29419     0/imm32/no-imm32
29420     0/imm32/no-imm8
29421     1/imm32/disp32-is-first-inout
29422     0/imm32/no-xm32
29423     0/imm32/no-x32
29424     0x11/imm32/alloc-id:fake
29425     _Primitive-loop-if-float>-named/imm32/next
29426 _Primitive-loop-if-float>-named:  # (payload primitive)
29427     0x11/imm32/alloc-id:fake:payload
29428     0x11/imm32/alloc-id:fake
29429     _string-loop-if-float>/imm32/name
29430     0x11/imm32/alloc-id:fake
29431     Single-lit-var/imm32/inouts
29432     0/imm32/no-outputs
29433     0/imm32/no-outputs
29434     0x11/imm32/alloc-id:fake
29435     _string_0f_87_jump_label/imm32/subx-name
29436     0/imm32/no-rm32
29437     0/imm32/no-r32
29438     0/imm32/no-imm32
29439     0/imm32/no-imm8
29440     1/imm32/disp32-is-first-inout
29441     0/imm32/no-xm32
29442     0/imm32/no-x32
29443     0/imm32/next
29444     0/imm32/next
29445 
29446 # string literals for Mu instructions
29447 _string-add:  # (payload array byte)
29448     0x11/imm32/alloc-id:fake:payload
29449     # "add"
29450     0x3/imm32/size
29451     0x61/a 0x64/d 0x64/d
29452 _string-address:  # (payload array byte)
29453     0x11/imm32/alloc-id:fake:payload
29454     # "address"
29455     0x7/imm32/size
29456     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
29457 _string-add-to:  # (payload array byte)
29458     0x11/imm32/alloc-id:fake:payload
29459     # "add-to"
29460     0x6/imm32/size
29461     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
29462 _string-and:  # (payload array byte)
29463     0x11/imm32/alloc-id:fake:payload
29464     # "and"
29465     0x3/imm32/size
29466     0x61/a 0x6e/n 0x64/d
29467 _string-and-with:  # (payload array byte)
29468     0x11/imm32/alloc-id:fake:payload
29469     # "and-with"
29470     0x8/imm32/size
29471     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
29472 _string-break:  # (payload array byte)
29473     0x11/imm32/alloc-id:fake:payload
29474     # "break"
29475     0x5/imm32/size
29476     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
29477 _string-break-if-<:  # (payload array byte)
29478     0x11/imm32/alloc-id:fake:payload
29479     # "break-if-<"
29480     0xa/imm32/size
29481     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
29482 _string-break-if-<=:  # (payload array byte)
29483     0x11/imm32/alloc-id:fake:payload
29484     # "break-if-<="
29485     0xb/imm32/size
29486     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
29487 _string-break-if-=:  # (payload array byte)
29488     0x11/imm32/alloc-id:fake:payload
29489     # "break-if-="
29490     0xa/imm32/size
29491     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
29492 _string-break-if->:  # (payload array byte)
29493     0x11/imm32/alloc-id:fake:payload
29494     # "break-if->"
29495     0xa/imm32/size
29496     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
29497 _string-break-if->=:  # (payload array byte)
29498     0x11/imm32/alloc-id:fake:payload
29499     # "break-if->="
29500     0xb/imm32/size
29501     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
29502 _string-break-if-!=:  # (payload array byte)
29503     0x11/imm32/alloc-id:fake:payload
29504     # "break-if-!="
29505     0xb/imm32/size
29506     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
29507 _string-break-if-addr<:  # (payload array byte)
29508     0x11/imm32/alloc-id:fake:payload
29509     # "break-if-addr<"
29510     0xe/imm32/size
29511     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/<
29512 _string-break-if-addr<=:  # (payload array byte)
29513     0x11/imm32/alloc-id:fake:payload
29514     # "break-if-addr<="
29515     0xf/imm32/size
29516     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/=
29517 _string-break-if-addr>:  # (payload array byte)
29518     0x11/imm32/alloc-id:fake:payload
29519     # "break-if-addr>"
29520     0xe/imm32/size
29521     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/>
29522 _string-break-if-addr>=:  # (payload array byte)
29523     0x11/imm32/alloc-id:fake:payload
29524     # "break-if-addr>="
29525     0xf/imm32/size
29526     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/=
29527 _string-break-if-float<:  # (payload array byte)
29528     0x11/imm32/alloc-id:fake:payload
29529     # "break-if-float<"
29530     0xf/imm32/size
29531     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/<
29532 _string-break-if-float<=:  # (payload array byte)
29533     0x11/imm32/alloc-id:fake:payload
29534     # "break-if-float<="
29535     0x10/imm32/size
29536     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/=
29537 _string-break-if-float>:  # (payload array byte)
29538     0x11/imm32/alloc-id:fake:payload
29539     # "break-if-float>"
29540     0xf/imm32/size
29541     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/>
29542 _string-break-if-float>=:  # (payload array byte)
29543     0x11/imm32/alloc-id:fake:payload
29544     # "break-if-float>="
29545     0x10/imm32/size
29546     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/=
29547 _string-compare:  # (payload array byte)
29548     0x11/imm32/alloc-id:fake:payload
29549     # "compare"
29550     0x7/imm32/size
29551     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
29552 _string-copy:  # (payload array byte)
29553     0x11/imm32/alloc-id:fake:payload
29554     # "copy"
29555     0x4/imm32/size
29556     0x63/c 0x6f/o 0x70/p 0x79/y
29557 _string-copy-to:  # (payload array byte)
29558     0x11/imm32/alloc-id:fake:payload
29559     # "copy-to"
29560     0x7/imm32/size
29561     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
29562 _string-copy-byte:
29563     0x11/imm32/alloc-id:fake:payload
29564     # "copy-byte"
29565     0x9/imm32/size
29566     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
29567 _string-copy-byte-to:
29568     0x11/imm32/alloc-id:fake:payload
29569     # "copy-byte-to"
29570     0xc/imm32/size
29571     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
29572 _string-decrement:  # (payload array byte)
29573     0x11/imm32/alloc-id:fake:payload
29574     # "decrement"
29575     0x9/imm32/size
29576     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
29577 _string-increment:  # (payload array byte)
29578     0x11/imm32/alloc-id:fake:payload
29579     # "increment"
29580     0x9/imm32/size
29581     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
29582 _string-loop:  # (payload array byte)
29583     0x11/imm32/alloc-id:fake:payload
29584     # "loop"
29585     0x4/imm32/size
29586     0x6c/l 0x6f/o 0x6f/o 0x70/p
29587 _string-loop-if-<:  # (payload array byte)
29588     0x11/imm32/alloc-id:fake:payload
29589     # "loop-if-<"
29590     0x9/imm32/size
29591     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
29592 _string-loop-if-<=:  # (payload array byte)
29593     0x11/imm32/alloc-id:fake:payload
29594     # "loop-if-<="
29595     0xa/imm32/size
29596     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
29597 _string-loop-if-=:  # (payload array byte)
29598     0x11/imm32/alloc-id:fake:payload
29599     # "loop-if-="
29600     0x9/imm32/size
29601     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
29602 _string-loop-if->:  # (payload array byte)
29603     0x11/imm32/alloc-id:fake:payload
29604     # "loop-if->"
29605     0x9/imm32/size
29606     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
29607 _string-loop-if->=:  # (payload array byte)
29608     0x11/imm32/alloc-id:fake:payload
29609     # "loop-if->="
29610     0xa/imm32/size
29611     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
29612 _string-loop-if-!=:  # (payload array byte)
29613     0x11/imm32/alloc-id:fake:payload
29614     # "loop-if-!="
29615     0xa/imm32/size
29616     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
29617 _string-loop-if-addr<:  # (payload array byte)
29618     0x11/imm32/alloc-id:fake:payload
29619     # "loop-if-addr<"
29620     0xd/imm32/size
29621     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/<
29622 _string-loop-if-addr<=:  # (payload array byte)
29623     0x11/imm32/alloc-id:fake:payload
29624     # "loop-if-addr<="
29625     0xe/imm32/size
29626     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/=
29627 _string-loop-if-addr>:  # (payload array byte)
29628     0x11/imm32/alloc-id:fake:payload
29629     # "loop-if-addr>"
29630     0xd/imm32/size
29631     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/>
29632 _string-loop-if-addr>=:  # (payload array byte)
29633     0x11/imm32/alloc-id:fake:payload
29634     # "loop-if-addr>="
29635     0xe/imm32/size
29636     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/=
29637 _string-loop-if-float<:  # (payload array byte)
29638     0x11/imm32/alloc-id:fake:payload
29639     # "loop-if-float<"
29640     0xe/imm32/size
29641     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/<
29642 _string-loop-if-float<=:  # (payload array byte)
29643     0x11/imm32/alloc-id:fake:payload
29644     # "loop-if-float<="
29645     0xf/imm32/size
29646     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/=
29647 _string-loop-if-float>:  # (payload array byte)
29648     0x11/imm32/alloc-id:fake:payload
29649     # "loop-if-float>"
29650     0xe/imm32/size
29651     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/>
29652 _string-loop-if-float>=:  # (payload array byte)
29653     0x11/imm32/alloc-id:fake:payload
29654     # "loop-if-float>="
29655     0xf/imm32/size
29656     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/=
29657 _string-multiply:  # (payload array byte)
29658     0x11/imm32/alloc-id:fake:payload
29659     # "multiply"
29660     0x8/imm32/size
29661     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
29662 _string-convert:  # (payload array byte)
29663     0x11/imm32/alloc-id:fake:payload
29664     # "convert"
29665     0x7/imm32/size
29666     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
29667 _string-truncate:  # (payload array byte)
29668     0x11/imm32/alloc-id:fake:payload
29669     # "truncate"
29670     0x8/imm32/size
29671     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
29672 _string-reinterpret:  # (payload array byte)
29673     0x11/imm32/alloc-id:fake:payload
29674     # "reinterpret"
29675     0xb/imm32/size
29676     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
29677 _string-divide:
29678     0x11/imm32/alloc-id:fake:payload
29679     # "divide"
29680     0x6/imm32/size
29681     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
29682 _string-max:
29683     0x11/imm32/alloc-id:fake:payload
29684     # "max"
29685     0x3/imm32/size
29686     0x6d/m 0x61/a 0x78/x
29687 _string-min:
29688     0x11/imm32/alloc-id:fake:payload
29689     # "min"
29690     0x3/imm32/size
29691     0x6d/m 0x69/i 0x6e/n
29692 _string-reciprocal:
29693     0x11/imm32/alloc-id:fake:payload
29694     # "reciprocal"
29695     0xa/imm32/size
29696     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
29697 _string-square-root:
29698     0x11/imm32/alloc-id:fake:payload
29699     # "square-root"
29700     0xb/imm32/size
29701     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
29702 _string-inverse-square-root:
29703     0x11/imm32/alloc-id:fake:payload
29704     # "inverse-square-root"
29705     0x13/imm32/size
29706     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
29707 _string-negate:  # (payload array byte)
29708     0x11/imm32/alloc-id:fake:payload
29709     # "negate"
29710     0x6/imm32/size
29711     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
29712 _string-or:  # (payload array byte)
29713     0x11/imm32/alloc-id:fake:payload
29714     # "or"
29715     0x2/imm32/size
29716     0x6f/o 0x72/r
29717 _string-or-with:  # (payload array byte)
29718     0x11/imm32/alloc-id:fake:payload
29719     # "or-with"
29720     0x7/imm32/size
29721     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
29722 _string-subtract:  # (payload array byte)
29723     0x11/imm32/alloc-id:fake:payload
29724     # "subtract"
29725     0x8/imm32/size
29726     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
29727 _string-subtract-from:  # (payload array byte)
29728     0x11/imm32/alloc-id:fake:payload
29729     # "subtract-from"
29730     0xd/imm32/size
29731     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
29732 _string-xor:  # (payload array byte)
29733     0x11/imm32/alloc-id:fake:payload
29734     # "xor"
29735     0x3/imm32/size
29736     0x78/x 0x6f/o 0x72/r
29737 _string-xor-with:  # (payload array byte)
29738     0x11/imm32/alloc-id:fake:payload
29739     # "xor-with"
29740     0x8/imm32/size
29741     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
29742 _string-shift-left:  # (payload array byte)
29743     0x11/imm32/alloc-id:fake:payload
29744     # "shift-left"
29745     0xa/imm32/size
29746     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
29747 _string-shift-right:  # (payload array byte)
29748     0x11/imm32/alloc-id:fake:payload
29749     # "shift-right"
29750     0xb/imm32/size
29751     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
29752 _string-shift-right-signed:  # (payload array byte)
29753     0x11/imm32/alloc-id:fake:payload
29754     # "shift-right-signed"
29755     0x12/imm32/size
29756     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
29757 
29758 # string literals for SubX instructions
29759 _string_01_add_to:  # (payload array byte)
29760     0x11/imm32/alloc-id:fake:payload
29761     # "01/add-to"
29762     0x9/imm32/size
29763     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
29764 _string_03_add:  # (payload array byte)
29765     0x11/imm32/alloc-id:fake:payload
29766     # "03/add"
29767     0x6/imm32/size
29768     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
29769 _string_05_add_to_eax:  # (payload array byte)
29770     0x11/imm32/alloc-id:fake:payload
29771     # "05/add-to-eax"
29772     0xd/imm32/size
29773     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
29774 _string_09_or_with:  # (payload array byte)
29775     0x11/imm32/alloc-id:fake:payload
29776     # "09/or-with"
29777     0xa/imm32/size
29778     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
29779 _string_0b_or:  # (payload array byte)
29780     0x11/imm32/alloc-id:fake:payload
29781     # "0b/or"
29782     0x5/imm32/size
29783     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
29784 _string_0d_or_with_eax:  # (payload array byte)
29785     0x11/imm32/alloc-id:fake:payload
29786     # "0d/or-with-eax"
29787     0xe/imm32/size
29788     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
29789 _string_0f_82_jump_label:  # (payload array byte)
29790     0x11/imm32/alloc-id:fake:payload
29791     # "0f 82/jump-if-addr<"
29792     0x13/imm32/size
29793     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/<
29794 _string_0f_82_jump_break:  # (payload array byte)
29795     0x11/imm32/alloc-id:fake:payload
29796     # "0f 82/jump-if-addr< break/disp32"
29797     0x20/imm32/size
29798     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
29799 _string_0f_82_jump_loop:  # (payload array byte)
29800     0x11/imm32/alloc-id:fake:payload
29801     # "0f 82/jump-if-addr< loop/disp32"
29802     0x1f/imm32/size
29803     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
29804 _string_0f_83_jump_label:  # (payload array byte)
29805     0x11/imm32/alloc-id:fake:payload
29806     # "0f 83/jump-if-addr>="
29807     0x14/imm32/size
29808     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/=
29809 _string_0f_83_jump_break:  # (payload array byte)
29810     0x11/imm32/alloc-id:fake:payload
29811     # "0f 83/jump-if-addr>= break/disp32"
29812     0x21/imm32/size
29813     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
29814 _string_0f_83_jump_loop:  # (payload array byte)
29815     0x11/imm32/alloc-id:fake:payload
29816     # "0f 83/jump-if-addr>= loop/disp32"
29817     0x20/imm32/size
29818     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
29819 _string_0f_84_jump_label:  # (payload array byte)
29820     0x11/imm32/alloc-id:fake:payload
29821     # "0f 84/jump-if-="
29822     0xf/imm32/size
29823     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/=
29824 _string_0f_84_jump_break:  # (payload array byte)
29825     0x11/imm32/alloc-id:fake:payload
29826     # "0f 84/jump-if-= break/disp32"
29827     0x1c/imm32/size
29828     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
29829 _string_0f_84_jump_loop:  # (payload array byte)
29830     0x11/imm32/alloc-id:fake:payload
29831     # "0f 84/jump-if-= loop/disp32"
29832     0x1b/imm32/size
29833     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
29834 _string_0f_85_jump_label:  # (payload array byte)
29835     0x11/imm32/alloc-id:fake:payload
29836     # "0f 85/jump-if-!="
29837     0x10/imm32/size
29838     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/=
29839 _string_0f_85_jump_break:  # (payload array byte)
29840     0x11/imm32/alloc-id:fake:payload
29841     # "0f 85/jump-if-!= break/disp32"
29842     0x1d/imm32/size
29843     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
29844 _string_0f_85_jump_loop:  # (payload array byte)
29845     0x11/imm32/alloc-id:fake:payload
29846     # "0f 85/jump-if-!= loop/disp32"
29847     0x1c/imm32/size
29848     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
29849 _string_0f_86_jump_label:  # (payload array byte)
29850     0x11/imm32/alloc-id:fake:payload
29851     # "0f 86/jump-if-addr<="
29852     0x14/imm32/size
29853     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/=
29854 _string_0f_86_jump_break:  # (payload array byte)
29855     0x11/imm32/alloc-id:fake:payload
29856     # "0f 86/jump-if-addr<= break/disp32"
29857     0x21/imm32/size
29858     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
29859 _string_0f_86_jump_loop:  # (payload array byte)
29860     0x11/imm32/alloc-id:fake:payload
29861     # "0f 86/jump-if-addr<= loop/disp32"
29862     0x20/imm32/size
29863     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
29864 _string_0f_87_jump_label:  # (payload array byte)
29865     0x11/imm32/alloc-id:fake:payload
29866     # "0f 87/jump-if-addr>"
29867     0x13/imm32/size
29868     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/>
29869 _string_0f_87_jump_break:  # (payload array byte)
29870     0x11/imm32/alloc-id:fake:payload
29871     # "0f 87/jump-if-addr> break/disp32"
29872     0x20/imm32/size
29873     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
29874 _string_0f_87_jump_loop:  # (payload array byte)
29875     0x11/imm32/alloc-id:fake:payload
29876     # "0f 87/jump-if-addr> loop/disp32"
29877     0x1f/imm32/size
29878     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
29879 _string_0f_8c_jump_label:  # (payload array byte)
29880     0x11/imm32/alloc-id:fake:payload
29881     # "0f 8c/jump-if-<"
29882     0xf/imm32/size
29883     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/<
29884 _string_0f_8c_jump_break:  # (payload array byte)
29885     0x11/imm32/alloc-id:fake:payload
29886     # "0f 8c/jump-if-< break/disp32"
29887     0x1c/imm32/size
29888     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
29889 _string_0f_8c_jump_loop:  # (payload array byte)
29890     0x11/imm32/alloc-id:fake:payload
29891     # "0f 8c/jump-if-< loop/disp32"
29892     0x1b/imm32/size
29893     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
29894 _string_0f_8d_jump_label:  # (payload array byte)
29895     0x11/imm32/alloc-id:fake:payload
29896     # "0f 8d/jump-if->="
29897     0x10/imm32/size
29898     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/=
29899 _string_0f_8d_jump_break:  # (payload array byte)
29900     0x11/imm32/alloc-id:fake:payload
29901     # "0f 8d/jump-if->= break/disp32"
29902     0x1d/imm32/size
29903     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
29904 _string_0f_8d_jump_loop:  # (payload array byte)
29905     0x11/imm32/alloc-id:fake:payload
29906     # "0f 8d/jump-if->= loop/disp32"
29907     0x1c/imm32/size
29908     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
29909 _string_0f_8e_jump_label:  # (payload array byte)
29910     0x11/imm32/alloc-id:fake:payload
29911     # "0f 8e/jump-if-<="
29912     0x10/imm32/size
29913     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/=
29914 _string_0f_8e_jump_break:  # (payload array byte)
29915     0x11/imm32/alloc-id:fake:payload
29916     # "0f 8e/jump-if-<= break/disp32"
29917     0x1d/imm32/size
29918     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
29919 _string_0f_8e_jump_loop:  # (payload array byte)
29920     0x11/imm32/alloc-id:fake:payload
29921     # "0f 8e/jump-if-<= loop/disp32"
29922     0x1c/imm32/size
29923     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
29924 _string_0f_8f_jump_label:  # (payload array byte)
29925     0x11/imm32/alloc-id:fake:payload
29926     # "0f 8f/jump-if->"
29927     0xf/imm32/size
29928     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/>
29929 _string_0f_8f_jump_break:  # (payload array byte)
29930     0x11/imm32/alloc-id:fake:payload
29931     # "0f 8f/jump-if-> break/disp32"
29932     0x1c/imm32/size
29933     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
29934 _string_0f_8f_jump_loop:  # (payload array byte)
29935     0x11/imm32/alloc-id:fake:payload
29936     # "0f 8f/jump-if-> loop/disp32"
29937     0x1b/imm32/size
29938     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
29939 _string_0f_af_multiply:  # (payload array byte)
29940     0x11/imm32/alloc-id:fake:payload
29941     # "0f af/multiply"
29942     0xe/imm32/size
29943     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
29944 _string_f3_0f_2a_convert_to_float:
29945     0x11/imm32/alloc-id:fake:payload
29946     # "f3 0f 2a/convert-to-float"
29947     0x19/imm32/size
29948     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
29949 _string_f3_0f_2d_convert_to_int:
29950     0x11/imm32/alloc-id:fake:payload
29951     # "f3 0f 2d/convert-to-int"
29952     0x17/imm32/size
29953     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
29954 _string_f3_0f_2c_truncate_to_int:
29955     0x11/imm32/alloc-id:fake:payload
29956     # "f3 0f 2c/truncate-to-int"
29957     0x18/imm32/size
29958     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
29959 _string_f3_0f_58_add:
29960     0x11/imm32/alloc-id:fake:payload
29961     # "f3 0f 58/add"
29962     0xc/imm32/size
29963     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
29964 _string_f3_0f_5c_subtract:
29965     0x11/imm32/alloc-id:fake:payload
29966     # "f3 0f 5c/subtract"
29967     0x11/imm32/size
29968     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
29969 _string_f3_0f_59_multiply:
29970     0x11/imm32/alloc-id:fake:payload
29971     # "f3 0f 59/multiply"
29972     0x11/imm32/size
29973     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
29974 _string_f3_0f_5e_divide:
29975     0x11/imm32/alloc-id:fake:payload
29976     # "f3 0f 5e/divide"
29977     0xf/imm32/size
29978     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
29979 _string_f3_0f_53_reciprocal:
29980     0x11/imm32/alloc-id:fake:payload
29981     # "f3 0f 53/reciprocal"
29982     0x13/imm32/size
29983     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
29984 _string_f3_0f_51_square_root:
29985     0x11/imm32/alloc-id:fake:payload
29986     # "f3 0f 51/square-root"
29987     0x14/imm32/size
29988     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
29989 _string_f3_0f_52_inverse_square_root:
29990     0x11/imm32/alloc-id:fake:payload
29991     # "f3 0f 52/inverse-square-root"
29992     0x1c/imm32/size
29993     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
29994 _string_f3_0f_5d_min:
29995     0x11/imm32/alloc-id:fake:payload
29996     # "f3 0f 5d/min"
29997     0xc/imm32/size
29998     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
29999 _string_f3_0f_5f_max:
30000     0x11/imm32/alloc-id:fake:payload
30001     # "f3 0f 5f/max"
30002     0xc/imm32/size
30003     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
30004 _string_f3_0f_10_copy:
30005     0x11/imm32/alloc-id:fake:payload
30006     # "f3 0f 10/copy"
30007     0xd/imm32/size
30008     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
30009 _string_f3_0f_11_copy:
30010     0x11/imm32/alloc-id:fake:payload
30011     # "f3 0f 11/copy"
30012     0xd/imm32/size
30013     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
30014 _string_0f_2f_compare:
30015     0x11/imm32/alloc-id:fake:payload
30016     # "0f 2f/compare"
30017     0xd/imm32/size
30018     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
30019 _string_21_and_with:  # (payload array byte)
30020     0x11/imm32/alloc-id:fake:payload
30021     # "21/and-with"
30022     0xb/imm32/size
30023     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30024 _string_23_and:  # (payload array byte)
30025     0x11/imm32/alloc-id:fake:payload
30026     # "23/and"
30027     0x6/imm32/size
30028     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
30029 _string_25_and_with_eax:  # (payload array byte)
30030     0x11/imm32/alloc-id:fake:payload
30031     # "25/and-with-eax"
30032     0xf/imm32/size
30033     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
30034 _string_29_subtract_from:  # (payload array byte)
30035     0x11/imm32/alloc-id:fake:payload
30036     # "29/subtract-from"
30037     0x10/imm32/size
30038     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
30039 _string_2b_subtract:  # (payload array byte)
30040     0x11/imm32/alloc-id:fake:payload
30041     # "2b/subtract"
30042     0xb/imm32/size
30043     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
30044 _string_2d_subtract_from_eax:  # (payload array byte)
30045     0x11/imm32/alloc-id:fake:payload
30046     # "2d/subtract-from-eax"
30047     0x14/imm32/size
30048     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
30049 _string_31_xor_with:  # (payload array byte)
30050     0x11/imm32/alloc-id:fake:payload
30051     # "31/xor-with"
30052     0xb/imm32/size
30053     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30054 _string_33_xor:  # (payload array byte)
30055     0x11/imm32/alloc-id:fake:payload
30056     # "33/xor"
30057     0x6/imm32/size
30058     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
30059 _string_35_xor_with_eax:  # (payload array byte)
30060     0x11/imm32/alloc-id:fake:payload
30061     # "35/xor-with-eax"
30062     0xf/imm32/size
30063     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
30064 _string_39_compare->:  # (payload array byte)
30065     0x11/imm32/alloc-id:fake:payload
30066     # "39/compare->"
30067     0xc/imm32/size
30068     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
30069 _string_3b_compare<-:  # (payload array byte)
30070     0x11/imm32/alloc-id:fake:payload
30071     # "3b/compare<-"
30072     0xc/imm32/size
30073     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
30074 _string_3d_compare_eax_with:  # (payload array byte)
30075     0x11/imm32/alloc-id:fake:payload
30076     # "3d/compare-eax-with"
30077     0x13/imm32/size
30078     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
30079 _string_40_increment_eax:  # (payload array byte)
30080     0x11/imm32/alloc-id:fake:payload
30081     # "40/increment-eax"
30082     0x10/imm32/size
30083     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
30084 _string_41_increment_ecx:  # (payload array byte)
30085     0x11/imm32/alloc-id:fake:payload
30086     # "41/increment-ecx"
30087     0x10/imm32/size
30088     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
30089 _string_42_increment_edx:  # (payload array byte)
30090     0x11/imm32/alloc-id:fake:payload
30091     # "42/increment-edx"
30092     0x10/imm32/size
30093     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
30094 _string_43_increment_ebx:  # (payload array byte)
30095     0x11/imm32/alloc-id:fake:payload
30096     # "43/increment-ebx"
30097     0x10/imm32/size
30098     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
30099 _string_46_increment_esi:  # (payload array byte)
30100     0x11/imm32/alloc-id:fake:payload
30101     # "46/increment-esi"
30102     0x10/imm32/size
30103     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
30104 _string_47_increment_edi:  # (payload array byte)
30105     0x11/imm32/alloc-id:fake:payload
30106     # "47/increment-edi"
30107     0x10/imm32/size
30108     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
30109 _string_48_decrement_eax:  # (payload array byte)
30110     0x11/imm32/alloc-id:fake:payload
30111     # "48/decrement-eax"
30112     0x10/imm32/size
30113     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
30114 _string_49_decrement_ecx:  # (payload array byte)
30115     0x11/imm32/alloc-id:fake:payload
30116     # "49/decrement-ecx"
30117     0x10/imm32/size
30118     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
30119 _string_4a_decrement_edx:  # (payload array byte)
30120     0x11/imm32/alloc-id:fake:payload
30121     # "4a/decrement-edx"
30122     0x10/imm32/size
30123     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
30124 _string_4b_decrement_ebx:  # (payload array byte)
30125     0x11/imm32/alloc-id:fake:payload
30126     # "4b/decrement-ebx"
30127     0x10/imm32/size
30128     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
30129 _string_4e_decrement_esi:  # (payload array byte)
30130     0x11/imm32/alloc-id:fake:payload
30131     # "4e/decrement-esi"
30132     0x10/imm32/size
30133     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
30134 _string_4f_decrement_edi:  # (payload array byte)
30135     0x11/imm32/alloc-id:fake:payload
30136     # "4f/decrement-edi"
30137     0x10/imm32/size
30138     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
30139 _string_81_subop_add:  # (payload array byte)
30140     0x11/imm32/alloc-id:fake:payload
30141     # "81 0/subop/add"
30142     0xe/imm32/size
30143     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
30144 _string_81_subop_or:  # (payload array byte)
30145     0x11/imm32/alloc-id:fake:payload
30146     # "81 1/subop/or"
30147     0xd/imm32/size
30148     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
30149 _string_81_subop_and:  # (payload array byte)
30150     0x11/imm32/alloc-id:fake:payload
30151     # "81 4/subop/and"
30152     0xe/imm32/size
30153     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
30154 _string_81_subop_subtract:  # (payload array byte)
30155     0x11/imm32/alloc-id:fake:payload
30156     # "81 5/subop/subtract"
30157     0x13/imm32/size
30158     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
30159 _string_81_subop_xor:  # (payload array byte)
30160     0x11/imm32/alloc-id:fake:payload
30161     # "81 6/subop/xor"
30162     0xe/imm32/size
30163     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
30164 _string_81_subop_compare:  # (payload array byte)
30165     0x11/imm32/alloc-id:fake:payload
30166     # "81 7/subop/compare"
30167     0x12/imm32/size
30168     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
30169 _string_89_<-:  # (payload array byte)
30170     0x11/imm32/alloc-id:fake:payload
30171     # "89/<-"
30172     0x5/imm32/size
30173     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
30174 _string_8b_->:  # (payload array byte)
30175     0x11/imm32/alloc-id:fake:payload
30176     # "8b/->"
30177     0x5/imm32/size
30178     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
30179 _string_8a_copy_byte:
30180     0x11/imm32/alloc-id:fake:payload
30181     # "8a/byte->"
30182     0x9/imm32/size
30183     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
30184 _string_88_copy_byte:
30185     0x11/imm32/alloc-id:fake:payload
30186     # "88/byte<-"
30187     0x9/imm32/size
30188     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
30189 _string_8d_copy_address:  # (payload array byte)
30190     0x11/imm32/alloc-id:fake:payload
30191     # "8d/copy-address"
30192     0xf/imm32/size
30193     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
30194 _string_b8_copy_to_eax:  # (payload array byte)
30195     0x11/imm32/alloc-id:fake:payload
30196     # "b8/copy-to-eax"
30197     0xe/imm32/size
30198     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
30199 _string_b9_copy_to_ecx:  # (payload array byte)
30200     0x11/imm32/alloc-id:fake:payload
30201     # "b9/copy-to-ecx"
30202     0xe/imm32/size
30203     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
30204 _string_ba_copy_to_edx:  # (payload array byte)
30205     0x11/imm32/alloc-id:fake:payload
30206     # "ba/copy-to-edx"
30207     0xe/imm32/size
30208     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
30209 _string_bb_copy_to_ebx:  # (payload array byte)
30210     0x11/imm32/alloc-id:fake:payload
30211     # "bb/copy-to-ebx"
30212     0xe/imm32/size
30213     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
30214 _string_be_copy_to_esi:  # (payload array byte)
30215     0x11/imm32/alloc-id:fake:payload
30216     # "be/copy-to-esi"
30217     0xe/imm32/size
30218     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
30219 _string_bf_copy_to_edi:  # (payload array byte)
30220     0x11/imm32/alloc-id:fake:payload
30221     # "bf/copy-to-edi"
30222     0xe/imm32/size
30223     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
30224 _string_c7_subop_copy:  # (payload array byte)
30225     0x11/imm32/alloc-id:fake:payload
30226     # "c7 0/subop/copy"
30227     0xf/imm32/size
30228     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
30229 _string_e9_jump_label:  # (payload array byte)
30230     0x11/imm32/alloc-id:fake:payload
30231     # "e9/jump"
30232     0x7/imm32/size
30233     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
30234 _string_e9_jump_break:  # (payload array byte)
30235     0x11/imm32/alloc-id:fake:payload
30236     # "e9/jump break/disp32"
30237     0x14/imm32/size
30238     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
30239 _string_e9_jump_loop:  # (payload array byte)
30240     0x11/imm32/alloc-id:fake:payload
30241     # "e9/jump loop/disp32"
30242     0x13/imm32/size
30243     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
30244 _string_f7_subop_negate:
30245     0x11/imm32/alloc-id:fake:payload
30246     # "f7 3/subop/negate"
30247     0x11/imm32/size
30248     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
30249 _string_ff_subop_increment:  # (payload array byte)
30250     0x11/imm32/alloc-id:fake:payload
30251     # "ff 0/subop/increment"
30252     0x14/imm32/size
30253     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
30254 _string_ff_subop_decrement:  # (payload array byte)
30255     0x11/imm32/alloc-id:fake:payload
30256     # "ff 1/subop/decrement"
30257     0x14/imm32/size
30258     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
30259 _string_c1_subop_shift_left:  # (payload array byte)
30260     0x11/imm32/alloc-id:fake:payload
30261     # "c1/shift 4/subop/left"
30262     0x15/imm32/size
30263     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
30264 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
30265     0x11/imm32/alloc-id:fake:payload
30266     # "c1/shift 5/subop/right-padding-zeroes"
30267     0x25/imm32/size
30268     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
30269 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
30270     0x11/imm32/alloc-id:fake:payload
30271     # "c1/shift 7/subop/right-preserving-sign"
30272     0x26/imm32/size
30273     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
30274 
30275 Single-int-var-in-mem:  # (payload list var)
30276     0x11/imm32/alloc-id:fake:payload
30277     0x11/imm32/alloc-id:fake
30278     Int-var-in-mem/imm32
30279     0/imm32/next
30280     0/imm32/next
30281 
30282 Int-var-in-mem:  # (payload var)
30283     0x11/imm32/alloc-id:fake:payload
30284     0/imm32/name
30285     0/imm32/name
30286     0x11/imm32/alloc-id:fake
30287     Type-int/imm32
30288     1/imm32/some-block-depth
30289     1/imm32/some-stack-offset
30290     0/imm32/no-register
30291     0/imm32/no-register
30292 
30293 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
30294 Single-byte-var-in-mem:  # (payload list var)
30295     0x11/imm32/alloc-id:fake:payload
30296     0x11/imm32/alloc-id:fake
30297     Byte-var-in-mem/imm32
30298     0/imm32/next
30299     0/imm32/next
30300 
30301 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
30302 Byte-var-in-mem:  # (payload var)
30303     0x11/imm32/alloc-id:fake:payload
30304     0/imm32/name
30305     0/imm32/name
30306     0x11/imm32/alloc-id:fake
30307     Type-byte/imm32
30308     1/imm32/some-block-depth
30309     1/imm32/some-stack-offset
30310     0/imm32/no-register
30311     0/imm32/no-register
30312 
30313 Two-args-int-stack-int-reg:  # (payload list var)
30314     0x11/imm32/alloc-id:fake:payload
30315     0x11/imm32/alloc-id:fake
30316     Int-var-in-mem/imm32
30317     0x11/imm32/alloc-id:fake
30318     Single-int-var-in-some-register/imm32/next
30319 
30320 Two-int-args-in-regs:  # (payload list var)
30321     0x11/imm32/alloc-id:fake:payload
30322     0x11/imm32/alloc-id:fake
30323     Int-var-in-some-register/imm32
30324     0x11/imm32/alloc-id:fake
30325     Single-int-var-in-some-register/imm32/next
30326 
30327 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
30328 Two-args-byte-stack-byte-reg:  # (payload list var)
30329     0x11/imm32/alloc-id:fake:payload
30330     0x11/imm32/alloc-id:fake
30331     Byte-var-in-mem/imm32
30332     0x11/imm32/alloc-id:fake
30333     Single-byte-var-in-some-register/imm32/next
30334 
30335 Two-args-int-reg-int-stack:  # (payload list var)
30336     0x11/imm32/alloc-id:fake:payload
30337     0x11/imm32/alloc-id:fake
30338     Int-var-in-some-register/imm32
30339     0x11/imm32/alloc-id:fake
30340     Single-int-var-in-mem/imm32/next
30341 
30342 Two-args-int-eax-int-literal:  # (payload list var)
30343     0x11/imm32/alloc-id:fake:payload
30344     0x11/imm32/alloc-id:fake
30345     Int-var-in-eax/imm32
30346     0x11/imm32/alloc-id:fake
30347     Single-lit-var/imm32/next
30348 
30349 Int-var-and-literal:  # (payload list var)
30350     0x11/imm32/alloc-id:fake:payload
30351     0x11/imm32/alloc-id:fake
30352     Int-var-in-mem/imm32
30353     0x11/imm32/alloc-id:fake
30354     Single-lit-var/imm32/next
30355 
30356 Int-var-in-register-and-literal:  # (payload list var)
30357     0x11/imm32/alloc-id:fake:payload
30358     0x11/imm32/alloc-id:fake
30359     Int-var-in-some-register/imm32
30360     0x11/imm32/alloc-id:fake
30361     Single-lit-var/imm32/next
30362 
30363 Two-float-args-in-regs:  # (payload list var)
30364     0x11/imm32/alloc-id:fake:payload
30365     0x11/imm32/alloc-id:fake
30366     Float-var-in-some-register/imm32
30367     0x11/imm32/alloc-id:fake
30368     Single-float-var-in-some-register/imm32/next
30369 
30370 Two-args-float-reg-float-stack:  # (payload list var)
30371     0x11/imm32/alloc-id:fake:payload
30372     0x11/imm32/alloc-id:fake
30373     Float-var-in-some-register/imm32
30374     0x11/imm32/alloc-id:fake
30375     Single-float-var-in-mem/imm32/next
30376 
30377 Two-args-float-stack-float-reg:  # (payload list var)
30378     0x11/imm32/alloc-id:fake:payload
30379     0x11/imm32/alloc-id:fake
30380     Float-var-in-mem/imm32
30381     0x11/imm32/alloc-id:fake
30382     Single-float-var-in-some-register/imm32/next
30383 
30384 Single-int-var-in-some-register:  # (payload list var)
30385     0x11/imm32/alloc-id:fake:payload
30386     0x11/imm32/alloc-id:fake
30387     Int-var-in-some-register/imm32
30388     0/imm32/next
30389     0/imm32/next
30390 
30391 Single-addr-var-in-some-register:  # (payload list var)
30392     0x11/imm32/alloc-id:fake:payload
30393     0x11/imm32/alloc-id:fake
30394     Addr-var-in-some-register/imm32
30395     0/imm32/next
30396     0/imm32/next
30397 
30398 Single-byte-var-in-some-register:  # (payload list var)
30399     0x11/imm32/alloc-id:fake:payload
30400     0x11/imm32/alloc-id:fake
30401     Byte-var-in-some-register/imm32
30402     0/imm32/next
30403     0/imm32/next
30404 
30405 Int-var-in-some-register:  # (payload var)
30406     0x11/imm32/alloc-id:fake:payload
30407     0/imm32/name
30408     0/imm32/name
30409     0x11/imm32/alloc-id:fake
30410     Type-int/imm32
30411     1/imm32/some-block-depth
30412     0/imm32/no-stack-offset
30413     0x11/imm32/alloc-id:fake
30414     Any-register/imm32
30415 
30416 Any-register:  # (payload array byte)
30417     0x11/imm32/alloc-id:fake:payload
30418     1/imm32/size
30419     # data
30420     2a/asterisk
30421 
30422 Addr-var-in-some-register:  # (payload var)
30423     0x11/imm32/alloc-id:fake:payload
30424     0/imm32/name
30425     0/imm32/name
30426     0x11/imm32/alloc-id:fake
30427     Type-addr/imm32
30428     1/imm32/some-block-depth
30429     0/imm32/no-stack-offset
30430     0x11/imm32/alloc-id:fake
30431     Any-register/imm32
30432 
30433 Byte-var-in-some-register:  # (payload var)
30434     0x11/imm32/alloc-id:fake:payload
30435     0/imm32/name
30436     0/imm32/name
30437     0x11/imm32/alloc-id:fake
30438     Type-byte/imm32
30439     1/imm32/some-block-depth
30440     0/imm32/no-stack-offset
30441     0x11/imm32/alloc-id:fake
30442     Any-register/imm32
30443 
30444 Single-int-var-in-eax:  # (payload list var)
30445     0x11/imm32/alloc-id:fake:payload
30446     0x11/imm32/alloc-id:fake
30447     Int-var-in-eax/imm32
30448     0/imm32/next
30449     0/imm32/next
30450 
30451 Int-var-in-eax:
30452     0x11/imm32/alloc-id:fake:payload
30453     0/imm32/name
30454     0/imm32/name
30455     0x11/imm32/alloc-id:fake
30456     Type-int/imm32
30457     1/imm32/some-block-depth
30458     0/imm32/no-stack-offset
30459     0x11/imm32/alloc-id:fake
30460     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
30461 
30462 Single-int-var-in-ecx:  # (payload list var)
30463     0x11/imm32/alloc-id:fake:payload
30464     0x11/imm32/alloc-id:fake
30465     Int-var-in-ecx/imm32
30466     0/imm32/next
30467     0/imm32/next
30468 
30469 Int-var-in-ecx:
30470     0x11/imm32/alloc-id:fake:payload
30471     0/imm32/name
30472     0/imm32/name
30473     0x11/imm32/alloc-id:fake
30474     Type-int/imm32
30475     1/imm32/some-block-depth
30476     0/imm32/no-stack-offset
30477     0x11/imm32/alloc-id:fake
30478     $Register-ecx/imm32/register
30479 
30480 Single-int-var-in-edx:  # (payload list var)
30481     0x11/imm32/alloc-id:fake:payload
30482     0x11/imm32/alloc-id:fake
30483     Int-var-in-edx/imm32
30484     0/imm32/next
30485     0/imm32/next
30486 
30487 Int-var-in-edx:  # (payload list var)
30488     0x11/imm32/alloc-id:fake:payload
30489     0/imm32/name
30490     0/imm32/name
30491     0x11/imm32/alloc-id:fake
30492     Type-int/imm32
30493     1/imm32/some-block-depth
30494     0/imm32/no-stack-offset
30495     0x11/imm32/alloc-id:fake
30496     $Register-edx/imm32/register
30497 
30498 Single-int-var-in-ebx:  # (payload list var)
30499     0x11/imm32/alloc-id:fake:payload
30500     0x11/imm32/alloc-id:fake
30501     Int-var-in-ebx/imm32
30502     0/imm32/next
30503     0/imm32/next
30504 
30505 Int-var-in-ebx:  # (payload list var)
30506     0x11/imm32/alloc-id:fake:payload
30507     0/imm32/name
30508     0/imm32/name
30509     0x11/imm32/alloc-id:fake
30510     Type-int/imm32
30511     1/imm32/some-block-depth
30512     0/imm32/no-stack-offset
30513     0x11/imm32/alloc-id:fake
30514     $Register-ebx/imm32/register
30515 
30516 Single-int-var-in-esi:  # (payload list var)
30517     0x11/imm32/alloc-id:fake:payload
30518     0x11/imm32/alloc-id:fake
30519     Int-var-in-esi/imm32
30520     0/imm32/next
30521     0/imm32/next
30522 
30523 Int-var-in-esi:  # (payload list var)
30524     0x11/imm32/alloc-id:fake:payload
30525     0/imm32/name
30526     0/imm32/name
30527     0x11/imm32/alloc-id:fake
30528     Type-int/imm32
30529     1/imm32/some-block-depth
30530     0/imm32/no-stack-offset
30531     0x11/imm32/alloc-id:fake
30532     $Register-esi/imm32/register
30533 
30534 Single-int-var-in-edi:  # (payload list var)
30535     0x11/imm32/alloc-id:fake:payload
30536     0x11/imm32/alloc-id:fake
30537     Int-var-in-edi/imm32
30538     0/imm32/next
30539     0/imm32/next
30540 
30541 Int-var-in-edi:  # (payload list var)
30542     0x11/imm32/alloc-id:fake:payload
30543     0/imm32/name
30544     0/imm32/name
30545     0x11/imm32/alloc-id:fake
30546     Type-int/imm32
30547     1/imm32/some-block-depth
30548     0/imm32/no-stack-offset
30549     0x11/imm32/alloc-id:fake
30550     $Register-edi/imm32/register
30551 
30552 Single-lit-var:  # (payload list var)
30553     0x11/imm32/alloc-id:fake:payload
30554     0x11/imm32/alloc-id:fake
30555     Lit-var/imm32
30556     0/imm32/next
30557     0/imm32/next
30558 
30559 Lit-var:  # (payload var)
30560     0x11/imm32/alloc-id:fake:payload
30561     0/imm32/name
30562     0/imm32/name
30563     0x11/imm32/alloc-id:fake
30564     Type-literal/imm32
30565     1/imm32/some-block-depth
30566     0/imm32/no-stack-offset
30567     0/imm32/no-register
30568     0/imm32/no-register
30569 
30570 Single-float-var-in-mem:  # (payload list var)
30571     0x11/imm32/alloc-id:fake:payload
30572     0x11/imm32/alloc-id:fake
30573     Float-var-in-mem/imm32
30574     0/imm32/next
30575     0/imm32/next
30576 
30577 Float-var-in-mem:  # (payload var)
30578     0x11/imm32/alloc-id:fake:payload
30579     0/imm32/name
30580     0/imm32/name
30581     0x11/imm32/alloc-id:fake
30582     Type-float/imm32
30583     1/imm32/some-block-depth
30584     1/imm32/some-stack-offset
30585     0/imm32/no-register
30586     0/imm32/no-register
30587 
30588 Single-float-var-in-some-register:  # (payload list var)
30589     0x11/imm32/alloc-id:fake:payload
30590     0x11/imm32/alloc-id:fake
30591     Float-var-in-some-register/imm32
30592     0/imm32/next
30593     0/imm32/next
30594 
30595 Float-var-in-some-register:  # (payload var)
30596     0x11/imm32/alloc-id:fake:payload
30597     0/imm32/name
30598     0/imm32/name
30599     0x11/imm32/alloc-id:fake
30600     Type-float/imm32
30601     1/imm32/some-block-depth
30602     0/imm32/no-stack-offset
30603     0x11/imm32/alloc-id:fake
30604     Any-register/imm32
30605 
30606 Type-int:  # (payload type-tree)
30607     0x11/imm32/alloc-id:fake:payload
30608     1/imm32/is-atom
30609     1/imm32/value:int
30610     0/imm32/left:unused
30611     0/imm32/right:null
30612     0/imm32/right:null
30613 
30614 Type-literal:  # (payload type-tree)
30615     0x11/imm32/alloc-id:fake:payload
30616     1/imm32/is-atom
30617     0/imm32/value:literal
30618     0/imm32/left:unused
30619     0/imm32/right:null
30620     0/imm32/right:null
30621 
30622 Type-addr:  # (payload type-tree)
30623     0x11/imm32/alloc-id:fake:payload
30624     1/imm32/is-atom
30625     2/imm32/value:addr
30626     0/imm32/left:unused
30627     0/imm32/right:null
30628     0/imm32/right:null
30629 
30630 Type-byte:  # (payload type-tree)
30631     0x11/imm32/alloc-id:fake:payload
30632     1/imm32/is-atom
30633     8/imm32/value:byte
30634     0/imm32/left:unused
30635     0/imm32/right:null
30636     0/imm32/right:null
30637 
30638 Type-float:  # (payload type-tree)
30639     0x11/imm32/alloc-id:fake:payload
30640     1/imm32/is-atom
30641     0xf/imm32/value:float
30642     0/imm32/left:unused
30643     0/imm32/right:null
30644     0/imm32/right:null
30645 
30646 == code
30647 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
30648     # . prologue
30649     55/push-ebp
30650     89/<- %ebp 4/r32/esp
30651     # . save registers
30652     50/push-eax
30653     51/push-ecx
30654     # ecx = primitive
30655     8b/-> *(ebp+0x10) 1/r32/ecx
30656     # emit primitive name
30657     (emit-indent *(ebp+8) *Curr-block-depth)
30658     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
30659     (write-buffered *(ebp+8) %eax)
30660     # emit rm32 if necessary
30661     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
30662     # emit xm32 if necessary
30663     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
30664     # emit r32 if necessary
30665     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
30666     # emit x32 if necessary
30667     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
30668     # emit imm32 if necessary
30669     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
30670     # emit imm8 if necessary
30671     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
30672     # emit disp32 if necessary
30673     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
30674     (write-buffered *(ebp+8) Newline)
30675 $emit-subx-primitive:end:
30676     # . restore registers
30677     59/pop-to-ecx
30678     58/pop-to-eax
30679     # . epilogue
30680     89/<- %esp 5/r32/ebp
30681     5d/pop-to-ebp
30682     c3/return
30683 
30684 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30685     # . prologue
30686     55/push-ebp
30687     89/<- %ebp 4/r32/esp
30688     # . save registers
30689     50/push-eax
30690     # if (l == 0) return
30691     81 7/subop/compare *(ebp+0xc) 0/imm32
30692     74/jump-if-= $emit-subx-rm32:end/disp8
30693     # var v/eax: (addr stmt-var)
30694     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
30695     (emit-subx-var-as-rm32 *(ebp+8) %eax)
30696 $emit-subx-rm32:end:
30697     # . restore registers
30698     58/pop-to-eax
30699     # . epilogue
30700     89/<- %esp 5/r32/ebp
30701     5d/pop-to-ebp
30702     c3/return
30703 
30704 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)
30705     # . prologue
30706     55/push-ebp
30707     89/<- %ebp 4/r32/esp
30708     # . save registers
30709     51/push-ecx
30710     # eax = l
30711     8b/-> *(ebp+0xc) 0/r32/eax
30712     # ecx = stmt
30713     8b/-> *(ebp+8) 1/r32/ecx
30714     # if (l == 1) return stmt->inouts
30715     {
30716       3d/compare-eax-and 1/imm32
30717       75/jump-if-!= break/disp8
30718 $get-stmt-operand-from-arg-location:1:
30719       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30720       eb/jump $get-stmt-operand-from-arg-location:end/disp8
30721     }
30722     # if (l == 2) return stmt->inouts->next
30723     {
30724       3d/compare-eax-and 2/imm32
30725       75/jump-if-!= break/disp8
30726 $get-stmt-operand-from-arg-location:2:
30727       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30728       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
30729       eb/jump $get-stmt-operand-from-arg-location:end/disp8
30730     }
30731     # if (l == 3) return stmt->outputs
30732     {
30733       3d/compare-eax-and 3/imm32
30734       75/jump-if-!= break/disp8
30735 $get-stmt-operand-from-arg-location:3:
30736       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
30737       eb/jump $get-stmt-operand-from-arg-location:end/disp8
30738     }
30739     # abort
30740     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
30741 $get-stmt-operand-from-arg-location:end:
30742     # . restore registers
30743     59/pop-to-ecx
30744     # . epilogue
30745     89/<- %esp 5/r32/ebp
30746     5d/pop-to-ebp
30747     c3/return
30748 
30749 $get-stmt-operand-from-arg-location:abort:
30750     # error("invalid arg-location " eax)
30751     (write-buffered *(ebp+0x10) "invalid arg-location ")
30752     (write-int32-hex-buffered *(ebp+0x10) %eax)
30753     (write-buffered *(ebp+0x10) Newline)
30754     (flush *(ebp+0x10))
30755     (stop *(ebp+0x14) 1)
30756     # never gets here
30757 
30758 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
30759     # . prologue
30760     55/push-ebp
30761     89/<- %ebp 4/r32/esp
30762     # . save registers
30763     50/push-eax
30764     51/push-ecx
30765     # if (l == 0) return
30766     81 7/subop/compare *(ebp+0xc) 0/imm32
30767     0f 84/jump-if-= $emit-subx-r32:end/disp32
30768     # var v/eax: (addr stmt-var)
30769     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
30770     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30771     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
30772 #?     (write-buffered Stderr "looking up ")
30773 #?     (write-buffered Stderr %eax)
30774 #?     (write-buffered Stderr Newline)
30775 #?     (flush Stderr)
30776     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
30777     (write-buffered *(ebp+8) Space)
30778     (write-int32-hex-buffered *(ebp+8) *eax)
30779     (write-buffered *(ebp+8) "/r32")
30780 $emit-subx-r32:end:
30781     # . restore registers
30782     59/pop-to-ecx
30783     58/pop-to-eax
30784     # . epilogue
30785     89/<- %esp 5/r32/ebp
30786     5d/pop-to-ebp
30787     c3/return
30788 
30789 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
30790     # . prologue
30791     55/push-ebp
30792     89/<- %ebp 4/r32/esp
30793     # . save registers
30794     50/push-eax
30795     51/push-ecx
30796     # if (l == 0) return
30797     81 7/subop/compare *(ebp+0xc) 0/imm32
30798     0f 84/jump-if-= $emit-subx-x32:end/disp32
30799     # var v/eax: (addr stmt-var)
30800     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
30801     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30802     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
30803 #?     (write-buffered Stderr "looking up ")
30804 #?     (write-buffered Stderr %eax)
30805 #?     (write-buffered Stderr Newline)
30806 #?     (flush Stderr)
30807     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
30808     (write-buffered *(ebp+8) Space)
30809     (write-int32-hex-buffered *(ebp+8) *eax)
30810     (write-buffered *(ebp+8) "/x32")
30811 $emit-subx-x32:end:
30812     # . restore registers
30813     59/pop-to-ecx
30814     58/pop-to-eax
30815     # . epilogue
30816     89/<- %esp 5/r32/ebp
30817     5d/pop-to-ebp
30818     c3/return
30819 
30820 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
30821     # . prologue
30822     55/push-ebp
30823     89/<- %ebp 4/r32/esp
30824     # . save registers
30825     50/push-eax
30826     51/push-ecx
30827     # if (l == 0) return
30828     81 7/subop/compare *(ebp+0xc) 0/imm32
30829     0f 84/jump-if-= $emit-subx-imm32:end/disp32
30830     # var v/eax: (handle var)
30831     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
30832     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30833     (lookup *eax *(eax+4))  # Var-name Var-name => eax
30834     (write-buffered *(ebp+8) Space)
30835     (write-buffered *(ebp+8) %eax)
30836     (write-buffered *(ebp+8) "/imm32")
30837 $emit-subx-imm32:end:
30838     # . restore registers
30839     59/pop-to-ecx
30840     58/pop-to-eax
30841     # . epilogue
30842     89/<- %esp 5/r32/ebp
30843     5d/pop-to-ebp
30844     c3/return
30845 
30846 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
30847     # . prologue
30848     55/push-ebp
30849     89/<- %ebp 4/r32/esp
30850     # . save registers
30851     50/push-eax
30852     51/push-ecx
30853     # if (l == 0) return
30854     81 7/subop/compare *(ebp+0xc) 0/imm32
30855     0f 84/jump-if-= $emit-subx-imm32:end/disp32
30856     # var v/eax: (handle var)
30857     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
30858     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30859     (lookup *eax *(eax+4))  # Var-name Var-name => eax
30860     (write-buffered *(ebp+8) Space)
30861     (write-buffered *(ebp+8) %eax)
30862     (write-buffered *(ebp+8) "/imm8")
30863 $emit-subx-imm8:end:
30864     # . restore registers
30865     59/pop-to-ecx
30866     58/pop-to-eax
30867     # . epilogue
30868     89/<- %esp 5/r32/ebp
30869     5d/pop-to-ebp
30870     c3/return
30871 
30872 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30873     # . prologue
30874     55/push-ebp
30875     89/<- %ebp 4/r32/esp
30876     # . save registers
30877     50/push-eax
30878     51/push-ecx
30879     # if (location == 0) return
30880     81 7/subop/compare *(ebp+0xc) 0/imm32
30881     0f 84/jump-if-= $emit-subx-disp32:end/disp32
30882     # var v/eax: (addr stmt-var)
30883     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
30884     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30885     (lookup *eax *(eax+4))  # Var-name Var-name => eax
30886     (write-buffered *(ebp+8) Space)
30887     (write-buffered *(ebp+8) %eax)
30888     # hack: if instruction operation starts with "break", emit ":break"
30889     # var name/ecx: (addr array byte) = lookup(stmt->operation)
30890     8b/-> *(ebp+0x10) 0/r32/eax
30891     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
30892     89/<- %ecx 0/r32/eax
30893     {
30894       (string-starts-with? %ecx "break")  # => eax
30895       3d/compare-eax-and 0/imm32/false
30896       74/jump-if-= break/disp8
30897       (write-buffered *(ebp+8) ":break")
30898     }
30899     # hack: if instruction operation starts with "loop", emit ":loop"
30900     {
30901       (string-starts-with? %ecx "loop")  # => eax
30902       3d/compare-eax-and 0/imm32/false
30903       74/jump-if-= break/disp8
30904       (write-buffered *(ebp+8) ":loop")
30905     }
30906     (write-buffered *(ebp+8) "/disp32")
30907 $emit-subx-disp32:end:
30908     # . restore registers
30909     59/pop-to-ecx
30910     58/pop-to-eax
30911     # . epilogue
30912     89/<- %esp 5/r32/ebp
30913     5d/pop-to-ebp
30914     c3/return
30915 
30916 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
30917     # . prologue
30918     55/push-ebp
30919     89/<- %ebp 4/r32/esp
30920     # . save registers
30921     50/push-eax
30922     51/push-ecx
30923     #
30924     (emit-indent *(ebp+8) *Curr-block-depth)
30925     (write-buffered *(ebp+8) "(")
30926     # ecx = stmt
30927     8b/-> *(ebp+0xc) 1/r32/ecx
30928     # - emit function name
30929     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
30930     (write-buffered *(ebp+8) %eax)
30931     # - emit arguments
30932     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
30933     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30934     {
30935       # if (curr == null) break
30936       3d/compare-eax-and 0/imm32
30937       74/jump-if-= break/disp8
30938       #
30939       (emit-subx-call-operand *(ebp+8) %eax)
30940       # curr = lookup(curr->next)
30941       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
30942       eb/jump loop/disp8
30943     }
30944     #
30945     (write-buffered *(ebp+8) ")\n")
30946 $emit-call:end:
30947     # . restore registers
30948     59/pop-to-ecx
30949     58/pop-to-eax
30950     # . epilogue
30951     89/<- %esp 5/r32/ebp
30952     5d/pop-to-ebp
30953     c3/return
30954 
30955 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
30956     # shares code with emit-subx-var-as-rm32
30957     # . prologue
30958     55/push-ebp
30959     89/<- %ebp 4/r32/esp
30960     # . save registers
30961     50/push-eax
30962     51/push-ecx
30963     56/push-esi
30964     # ecx = s
30965     8b/-> *(ebp+0xc) 1/r32/ecx
30966     # var operand/esi: (addr var) = lookup(s->value)
30967     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
30968     89/<- %esi 0/r32/eax
30969     # if (operand->register && !s->is-deref?) emit "%__"
30970     {
30971 $emit-subx-call-operand:check-for-register-direct:
30972       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
30973       74/jump-if-= break/disp8
30974       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
30975       75/jump-if-!= break/disp8
30976 $emit-subx-call-operand:register-direct:
30977       (write-buffered *(ebp+8) " %")
30978       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
30979       (write-buffered *(ebp+8) %eax)
30980       e9/jump $emit-subx-call-operand:end/disp32
30981     }
30982     # else if (operand->register && s->is-deref?) emit "*__"
30983     {
30984 $emit-subx-call-operand:check-for-register-indirect:
30985       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
30986       74/jump-if-= break/disp8
30987       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
30988       74/jump-if-= break/disp8
30989 $emit-subx-call-operand:register-indirect:
30990       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
30991       e9/jump $emit-subx-call-operand:end/disp32
30992     }
30993     # else if (operand->stack-offset) emit "*(ebp+__)"
30994     {
30995       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
30996       74/jump-if-= break/disp8
30997 $emit-subx-call-operand:stack:
30998       (emit-subx-call-operand-stack *(ebp+8) %esi)
30999       e9/jump $emit-subx-call-operand:end/disp32
31000     }
31001     # else if (operand->type == literal) emit "__"
31002     {
31003       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
31004       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-left
31005       75/jump-if-!= break/disp8
31006 $emit-subx-call-operand:literal:
31007       (write-buffered *(ebp+8) Space)
31008       (lookup *esi *(esi+4))  # Var-name Var-name => eax
31009       (write-buffered *(ebp+8) %eax)
31010     }
31011 $emit-subx-call-operand:end:
31012     # . restore registers
31013     5e/pop-to-esi
31014     59/pop-to-ecx
31015     58/pop-to-eax
31016     # . epilogue
31017     89/<- %esp 5/r32/ebp
31018     5d/pop-to-ebp
31019     c3/return
31020 
31021 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
31022     # . prologue
31023     55/push-ebp
31024     89/<- %ebp 4/r32/esp
31025     # . save registers
31026     50/push-eax
31027     51/push-ecx
31028     56/push-esi
31029     # esi = v
31030     8b/-> *(ebp+0xc) 6/r32/esi
31031     # var size/ecx: int = size-of-deref(v)
31032     (size-of-deref %esi)  # => eax
31033     89/<- %ecx 0/r32/eax
31034     # var reg-name/esi: (addr array byte) = lookup(v->register)
31035     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31036     89/<- %esi 0/r32/eax
31037     # TODO: assert size is a multiple of 4
31038     # var i/eax: int = 0
31039     b8/copy-to-eax 0/imm32
31040     {
31041 $emit-subx-call-operand-register-indirect:loop:
31042       # if (i >= size) break
31043       39/compare %eax 1/r32/ecx
31044       7d/jump-if->= break/disp8
31045       # emit " *(" v->register "+" i ")"
31046       (write-buffered *(ebp+8) " *(")
31047       (write-buffered *(ebp+8) %esi)
31048       (write-buffered *(ebp+8) "+")
31049       (write-int32-hex-buffered *(ebp+8) %eax)
31050       (write-buffered *(ebp+8) ")")
31051       # i += 4
31052       05/add-to-eax 4/imm32
31053       #
31054       eb/jump loop/disp8
31055     }
31056 $emit-subx-call-operand-register-indirect:end:
31057     # . restore registers
31058     5e/pop-to-esi
31059     59/pop-to-ecx
31060     58/pop-to-eax
31061     # . epilogue
31062     89/<- %esp 5/r32/ebp
31063     5d/pop-to-ebp
31064     c3/return
31065 
31066 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
31067     # . prologue
31068     55/push-ebp
31069     89/<- %ebp 4/r32/esp
31070     # . save registers
31071     50/push-eax
31072     51/push-ecx
31073     56/push-esi
31074     # esi = v
31075     8b/-> *(ebp+0xc) 6/r32/esi
31076     # var curr/ecx: int = v->offset
31077     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
31078     # var max/eax: int = v->offset + size-of(v)
31079     (size-of %esi)  # => eax
31080     # TODO: assert size is a multiple of 4
31081     01/add-to %eax 1/r32/ecx
31082     {
31083 $emit-subx-call-operand-stack:loop:
31084       # if (curr >= max) break
31085       39/compare %ecx 0/r32/eax
31086       7d/jump-if->= break/disp8
31087       # emit " *(ebp+" curr ")"
31088       (write-buffered *(ebp+8) " *(ebp+")
31089       (write-int32-hex-buffered *(ebp+8) %ecx)
31090       (write-buffered *(ebp+8) ")")
31091       # i += 4
31092       81 0/subop/add %ecx 4/imm32
31093       #
31094       eb/jump loop/disp8
31095     }
31096 $emit-subx-call-operand-stack:end:
31097     # . restore registers
31098     5e/pop-to-esi
31099     59/pop-to-ecx
31100     58/pop-to-eax
31101     # . epilogue
31102     89/<- %esp 5/r32/ebp
31103     5d/pop-to-ebp
31104     c3/return
31105 
31106 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
31107     # . prologue
31108     55/push-ebp
31109     89/<- %ebp 4/r32/esp
31110     # . save registers
31111     50/push-eax
31112     51/push-ecx
31113     56/push-esi
31114     # ecx = s
31115     8b/-> *(ebp+0xc) 1/r32/ecx
31116     # var operand/esi: (addr var) = lookup(s->value)
31117     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
31118     89/<- %esi 0/r32/eax
31119     # if (operand->register && s->is-deref?) emit "*__"
31120     {
31121 $emit-subx-var-as-rm32:check-for-register-indirect:
31122       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31123       74/jump-if-= break/disp8
31124       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31125       74/jump-if-= break/disp8
31126 $emit-subx-var-as-rm32:register-indirect:
31127       (write-buffered *(ebp+8) " *")
31128       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31129       (write-buffered *(ebp+8) %eax)
31130       e9/jump $emit-subx-var-as-rm32:end/disp32
31131     }
31132     # if (operand->register && !s->is-deref?) emit "%__"
31133     {
31134 $emit-subx-var-as-rm32:check-for-register-direct:
31135       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31136       74/jump-if-= break/disp8
31137       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31138       75/jump-if-!= break/disp8
31139 $emit-subx-var-as-rm32:register-direct:
31140       (write-buffered *(ebp+8) " %")
31141       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31142       (write-buffered *(ebp+8) %eax)
31143       e9/jump $emit-subx-var-as-rm32:end/disp32
31144     }
31145     # else if (operand->stack-offset) emit "*(ebp+__)"
31146     {
31147       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
31148       74/jump-if-= break/disp8
31149 $emit-subx-var-as-rm32:stack:
31150       (write-buffered *(ebp+8) Space)
31151       (write-buffered *(ebp+8) "*(ebp+")
31152       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
31153       (write-buffered *(ebp+8) ")")
31154     }
31155 $emit-subx-var-as-rm32:end:
31156     # . restore registers
31157     5e/pop-to-esi
31158     59/pop-to-ecx
31159     58/pop-to-eax
31160     # . epilogue
31161     89/<- %esp 5/r32/ebp
31162     5d/pop-to-ebp
31163     c3/return
31164 
31165 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
31166     # . prologue
31167     55/push-ebp
31168     89/<- %ebp 4/r32/esp
31169     # . save registers
31170     51/push-ecx
31171     # var curr/ecx: (addr primitive) = primitives
31172     8b/-> *(ebp+8) 1/r32/ecx
31173     {
31174 $find-matching-primitive:loop:
31175       # if (curr == null) break
31176       81 7/subop/compare %ecx 0/imm32
31177       74/jump-if-= break/disp8
31178       # if match(curr, stmt) return curr
31179       {
31180         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
31181         3d/compare-eax-and 0/imm32/false
31182         74/jump-if-= break/disp8
31183         89/<- %eax 1/r32/ecx
31184         eb/jump $find-matching-primitive:end/disp8
31185       }
31186 $find-matching-primitive:next-primitive:
31187       # curr = curr->next
31188       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
31189       89/<- %ecx 0/r32/eax
31190       #
31191       e9/jump loop/disp32
31192     }
31193     # return null
31194     b8/copy-to-eax 0/imm32
31195 $find-matching-primitive:end:
31196     # . restore registers
31197     59/pop-to-ecx
31198     # . epilogue
31199     89/<- %esp 5/r32/ebp
31200     5d/pop-to-ebp
31201     c3/return
31202 
31203 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
31204     # A mu stmt matches a primitive if the name matches, all the inout vars
31205     # match, and all the output vars match.
31206     # Vars match if types match and registers match.
31207     # In addition, a stmt output matches a primitive's output if types match
31208     # and the primitive has a wildcard register.
31209     # . prologue
31210     55/push-ebp
31211     89/<- %ebp 4/r32/esp
31212     # . save registers
31213     51/push-ecx
31214     52/push-edx
31215     53/push-ebx
31216     56/push-esi
31217     57/push-edi
31218     # ecx = stmt
31219     8b/-> *(ebp+8) 1/r32/ecx
31220     # edx = primitive
31221     8b/-> *(ebp+0xc) 2/r32/edx
31222     {
31223 $mu-stmt-matches-primitive?:check-name:
31224       # if (primitive->name != stmt->operation) return false
31225       # . var esi: (addr array byte) = lookup(stmt->operation)
31226       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
31227       89/<- %esi 0/r32/eax
31228       # . var edi: (addr array byte) = lookup(primitive->name)
31229       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
31230 #?       (write-buffered Stderr %eax)
31231 #?       (write-buffered Stderr Newline)
31232 #?       (flush Stderr)
31233       89/<- %edi 0/r32/eax
31234       (string-equal? %esi %edi)  # => eax
31235       3d/compare-eax-and 0/imm32/false
31236       75/jump-if-!= break/disp8
31237       b8/copy-to-eax 0/imm32
31238       e9/jump $mu-stmt-matches-primitive?:end/disp32
31239     }
31240     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
31241     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
31242     89/<- %esi 0/r32/eax
31243     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
31244     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
31245     89/<- %edi 0/r32/eax
31246     {
31247 $mu-stmt-matches-primitive?:inouts-loop:
31248       # if (curr == 0 && curr2 == 0) move on to check outputs
31249       {
31250 $mu-stmt-matches-primitive?:check-both-inouts-null:
31251         81 7/subop/compare %esi 0/imm32
31252         75/jump-if-!= break/disp8
31253 $mu-stmt-matches-primitive?:stmt-inout-null:
31254         81 7/subop/compare %edi 0/imm32
31255         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
31256 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
31257         # return false
31258         b8/copy-to-eax 0/imm32/false
31259         e9/jump $mu-stmt-matches-primitive?:end/disp32
31260       }
31261       # if (curr2 == 0) return false
31262       {
31263 $mu-stmt-matches-primitive?:check-prim-inout-null:
31264         81 7/subop/compare %edi 0/imm32
31265         75/jump-if-!= break/disp8
31266 $mu-stmt-matches-primitive?:prim-inout-null:
31267         b8/copy-to-eax 0/imm32/false
31268         e9/jump $mu-stmt-matches-primitive?:end/disp32
31269       }
31270       # if (curr != curr2) return false
31271       {
31272 $mu-stmt-matches-primitive?:check-inouts-match:
31273         (lookup *edi *(edi+4))  # List-value List-value => eax
31274         (operand-matches-primitive? %esi %eax)  # => eax
31275         3d/compare-eax-and 0/imm32/false
31276         75/jump-if-!= break/disp8
31277 $mu-stmt-matches-primitive?:inouts-match:
31278         b8/copy-to-eax 0/imm32/false
31279         e9/jump $mu-stmt-matches-primitive?:end/disp32
31280       }
31281 $mu-stmt-matches-primitive?:next-inout:
31282       # curr = lookup(curr->next)
31283       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
31284       89/<- %esi 0/r32/eax
31285       # curr2 = lookup(curr2->next)
31286       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
31287       89/<- %edi 0/r32/eax
31288       #
31289       e9/jump loop/disp32
31290     }
31291 $mu-stmt-matches-primitive?:check-outputs:
31292     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
31293     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
31294     89/<- %esi 0/r32/eax
31295     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
31296     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
31297     89/<- %edi 0/r32/eax
31298     {
31299 $mu-stmt-matches-primitive?:outputs-loop:
31300       # if (curr == 0) return (curr2 == 0)
31301       {
31302 $mu-stmt-matches-primitive?:check-both-outputs-null:
31303         81 7/subop/compare %esi 0/imm32
31304         75/jump-if-!= break/disp8
31305         {
31306 $mu-stmt-matches-primitive?:stmt-output-null:
31307           81 7/subop/compare %edi 0/imm32
31308           75/jump-if-!= break/disp8
31309 $mu-stmt-matches-primitive?:both-outputs-null:
31310           # return true
31311           b8/copy-to-eax 1/imm32
31312           e9/jump $mu-stmt-matches-primitive?:end/disp32
31313         }
31314 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
31315         # return false
31316         b8/copy-to-eax 0/imm32
31317         e9/jump $mu-stmt-matches-primitive?:end/disp32
31318       }
31319       # if (curr2 == 0) return false
31320       {
31321 $mu-stmt-matches-primitive?:check-prim-output-null:
31322         81 7/subop/compare %edi 0/imm32
31323         75/jump-if-!= break/disp8
31324 $mu-stmt-matches-primitive?:prim-output-is-null:
31325         b8/copy-to-eax 0/imm32
31326         e9/jump $mu-stmt-matches-primitive?:end/disp32
31327       }
31328       # if (curr != curr2) return false
31329       {
31330 $mu-stmt-matches-primitive?:check-outputs-match:
31331         (lookup *edi *(edi+4))  # List-value List-value => eax
31332         (operand-matches-primitive? %esi %eax)  # => eax
31333         3d/compare-eax-and 0/imm32/false
31334         75/jump-if-!= break/disp8
31335 $mu-stmt-matches-primitive?:outputs-match:
31336         b8/copy-to-eax 0/imm32
31337         e9/jump $mu-stmt-matches-primitive?:end/disp32
31338       }
31339 $mu-stmt-matches-primitive?:next-output:
31340       # curr = lookup(curr->next)
31341       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
31342       89/<- %esi 0/r32/eax
31343       # curr2 = lookup(curr2->next)
31344       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
31345       89/<- %edi 0/r32/eax
31346       #
31347       e9/jump loop/disp32
31348     }
31349 $mu-stmt-matches-primitive?:return-true:
31350     b8/copy-to-eax 1/imm32
31351 $mu-stmt-matches-primitive?:end:
31352     # . restore registers
31353     5f/pop-to-edi
31354     5e/pop-to-esi
31355     5b/pop-to-ebx
31356     5a/pop-to-edx
31357     59/pop-to-ecx
31358     # . epilogue
31359     89/<- %esp 5/r32/ebp
31360     5d/pop-to-ebp
31361     c3/return
31362 
31363 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
31364     # . prologue
31365     55/push-ebp
31366     89/<- %ebp 4/r32/esp
31367     # . save registers
31368     51/push-ecx
31369     52/push-edx
31370     53/push-ebx
31371     56/push-esi
31372     57/push-edi
31373     # ecx = s
31374     8b/-> *(ebp+8) 1/r32/ecx
31375     # var var/esi: (addr var) = lookup(s->value)
31376     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
31377     89/<- %esi 0/r32/eax
31378     # edi = prim-var
31379     8b/-> *(ebp+0xc) 7/r32/edi
31380 $operand-matches-primitive?:check-type:
31381     # if !category-match?(var->type, prim-var->type) return false
31382     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
31383     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
31384     89/<- %ebx 0/r32/eax
31385     # . if s is deref, vtype = vtype->right
31386     {
31387       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31388       74/jump-if-= break/disp8
31389 $operand-matches-primitive?:is-deref:
31390       # . var t/eax: (addr type)
31391       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
31392       # . if !t->is-atom? t = t->left
31393       81 7/subop/compare *eax 0/imm32/false
31394       {
31395         75/jump-if-!= break/disp8
31396         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
31397       }
31398       # .
31399       89/<- %ebx 0/r32/eax
31400     }
31401     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
31402     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
31403     (subx-type-category-match? %ebx %eax)  # => eax
31404     3d/compare-eax-and 0/imm32/false
31405     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
31406     {
31407 $operand-matches-primitive?:check-register:
31408       # if prim-var is in memory and var is in register but dereference, match
31409       {
31410         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
31411         0f 85/jump-if-!= break/disp32
31412         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31413         74/jump-if-= break/disp8
31414         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31415         74/jump-if-= break/disp8
31416 $operand-matches-primitive?:var-deref-match:
31417         e9/jump $operand-matches-primitive?:return-true/disp32
31418       }
31419       # if prim-var is in register and var is in register but dereference, no match
31420       {
31421         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
31422         0f 84/jump-if-= break/disp32
31423         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31424         0f 84/jump-if-= break/disp32
31425         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31426         74/jump-if-= break/disp8
31427 $operand-matches-primitive?:var-deref-no-match:
31428         e9/jump $operand-matches-primitive?:return-false/disp32
31429       }
31430       # return false if var->register doesn't match prim-var->register
31431       {
31432         # if register addresses are equal, it's a match
31433         # var vreg/ebx: (addr array byte) = lookup(var->register)
31434         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31435         89/<- %ebx 0/r32/eax
31436         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
31437         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
31438         89/<- %ecx 0/r32/eax
31439         # if (vreg == preg) break
31440         39/compare %ecx 3/r32/ebx
31441         74/jump-if-= break/disp8
31442 $operand-matches-primitive?:var-register-no-match:
31443         # if either address is 0, return false
31444         81 7/subop/compare %ebx 0/imm32
31445         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
31446         81 7/subop/compare %ecx 0/imm32
31447         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
31448         # if prim-var->register is wildcard, it's a match
31449         (string-equal? %ecx "*")  # Any-register => eax
31450         3d/compare-eax-and 0/imm32/false
31451         75/jump-if-!= break/disp8
31452 $operand-matches-primitive?:wildcard-no-match:
31453         # if string contents aren't equal, return false
31454         (string-equal? %ecx %ebx)  # => eax
31455         3d/compare-eax-and 0/imm32/false
31456         74/jump-if-= $operand-matches-primitive?:return-false/disp8
31457       }
31458     }
31459 $operand-matches-primitive?:return-true:
31460     b8/copy-to-eax 1/imm32/true
31461     eb/jump $operand-matches-primitive?:end/disp8
31462 $operand-matches-primitive?:return-false:
31463     b8/copy-to-eax 0/imm32/false
31464 $operand-matches-primitive?:end:
31465     # . restore registers
31466     5f/pop-to-edi
31467     5e/pop-to-esi
31468     5b/pop-to-ebx
31469     5a/pop-to-edx
31470     59/pop-to-ecx
31471     # . epilogue
31472     89/<- %esp 5/r32/ebp
31473     5d/pop-to-ebp
31474     c3/return
31475 
31476 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
31477     # . prologue
31478     55/push-ebp
31479     89/<- %ebp 4/r32/esp
31480     # . save registers
31481     51/push-ecx
31482     # var curr/ecx: (handle function) = functions
31483     8b/-> *(ebp+8) 1/r32/ecx
31484     {
31485       # if (curr == null) break
31486       81 7/subop/compare %ecx 0/imm32
31487       74/jump-if-= break/disp8
31488 #?       (write-buffered Stderr "iter\n")
31489 #?       (flush Stderr)
31490       # if match(stmt, curr) return curr
31491       {
31492         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
31493         3d/compare-eax-and 0/imm32/false
31494         74/jump-if-= break/disp8
31495         89/<- %eax 1/r32/ecx
31496         eb/jump $find-matching-function:end/disp8
31497       }
31498       # curr = curr->next
31499       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
31500       89/<- %ecx 0/r32/eax
31501       #
31502       eb/jump loop/disp8
31503     }
31504     # return null
31505     b8/copy-to-eax 0/imm32
31506 $find-matching-function:end:
31507     # . restore registers
31508     59/pop-to-ecx
31509     # . epilogue
31510     89/<- %esp 5/r32/ebp
31511     5d/pop-to-ebp
31512     c3/return
31513 
31514 # Just compare names; user-defined functions don't support overloading yet.
31515 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
31516     # . prologue
31517     55/push-ebp
31518     89/<- %ebp 4/r32/esp
31519     # . save registers
31520     51/push-ecx
31521     # return function->name == stmt->operation
31522     # ecx = lookup(stmt->operation)
31523     8b/-> *(ebp+8) 0/r32/eax
31524     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
31525     89/<- %ecx 0/r32/eax
31526     # eax = lookup(function->name)
31527     8b/-> *(ebp+0xc) 0/r32/eax
31528     (lookup *eax *(eax+4))  # Function-name Function-name => eax
31529     (string-equal? %eax %ecx)  # => eax
31530 $mu-stmt-matches-function?:end:
31531     # . restore registers
31532     59/pop-to-ecx
31533     # . epilogue
31534     89/<- %esp 5/r32/ebp
31535     5d/pop-to-ebp
31536     c3/return
31537 
31538 # Type-checking happens elsewhere. This method is for selecting between
31539 # primitives.
31540 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
31541     # . prologue
31542     55/push-ebp
31543     89/<- %ebp 4/r32/esp
31544     # . save registers
31545     51/push-ecx
31546     # var cata/ecx: int = type-category(a)
31547     (type-category *(ebp+8))  # => eax
31548     89/<- %ecx 0/r32/eax
31549     # var catb/eax: int = type-category(b)
31550     (type-category *(ebp+0xc))  # => eax
31551     # return cata == catb
31552     39/compare %eax 1/r32/ecx
31553     0f 94/set-byte-if-= %al
31554     81 4/subop/and %eax 0xff/imm32
31555 $subx-type-category-match?:end:
31556     # . restore registers
31557     59/pop-to-ecx
31558     # . epilogue
31559     89/<- %esp 5/r32/ebp
31560     5d/pop-to-ebp
31561     c3/return
31562 
31563 type-category:  # a: (addr type-tree) -> result/eax: int
31564     # . prologue
31565     55/push-ebp
31566     89/<- %ebp 4/r32/esp
31567     # . save registers
31568     51/push-ecx
31569     # var lit?/ecx: boolean = is-literal-type?(a)
31570     (is-simple-mu-type? *(ebp+8) 0)  # => eax
31571     89/<- %ecx 0/r32/eax
31572     # var float?/eax: int = is-float?(a)
31573     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
31574     # set bits for lit? and float?
31575     c1/shift 4/subop/left %ecx 1/imm8
31576     09/or %eax 1/r32/ecx
31577 $type-category:end:
31578     # . restore registers
31579     59/pop-to-ecx
31580     # . epilogue
31581     89/<- %esp 5/r32/ebp
31582     5d/pop-to-ebp
31583     c3/return
31584 
31585 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
31586     # . prologue
31587     55/push-ebp
31588     89/<- %ebp 4/r32/esp
31589     # . save registers
31590     51/push-ecx
31591     # ecx = n
31592     8b/-> *(ebp+0xc) 1/r32/ecx
31593     # return (a->value == n)
31594     8b/-> *(ebp+8) 0/r32/eax
31595     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
31596     0f 94/set-byte-if-= %al
31597     81 4/subop/and %eax 0xff/imm32
31598 $is-simple-mu-type?:end:
31599     # . restore registers
31600     59/pop-to-ecx
31601     # . epilogue
31602     89/<- %esp 5/r32/ebp
31603     5d/pop-to-ebp
31604     c3/return
31605 
31606 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
31607     # . prologue
31608     55/push-ebp
31609     89/<- %ebp 4/r32/esp
31610     # eax = a
31611     8b/-> *(ebp+8) 0/r32/eax
31612     # if (!a->is-atom?) a = a->left
31613     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
31614     {
31615       75/jump-if-!= break/disp8
31616       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
31617     }
31618     # return (a->value == addr)
31619     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
31620     0f 94/set-byte-if-= %al
31621     81 4/subop/and %eax 0xff/imm32
31622 $is-mu-addr-type?:end:
31623     # . epilogue
31624     89/<- %esp 5/r32/ebp
31625     5d/pop-to-ebp
31626     c3/return
31627 
31628 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
31629     # . prologue
31630     55/push-ebp
31631     89/<- %ebp 4/r32/esp
31632     # eax = a
31633     8b/-> *(ebp+8) 0/r32/eax
31634     # if (!a->is-atom?) a = a->left
31635     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
31636     {
31637       75/jump-if-!= break/disp8
31638       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
31639     }
31640     # return (a->value == array)
31641     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
31642     0f 94/set-byte-if-= %al
31643     81 4/subop/and %eax 0xff/imm32
31644 $is-mu-array-type?:end:
31645     # . epilogue
31646     89/<- %esp 5/r32/ebp
31647     5d/pop-to-ebp
31648     c3/return
31649 
31650 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
31651     # . prologue
31652     55/push-ebp
31653     89/<- %ebp 4/r32/esp
31654     # eax = a
31655     8b/-> *(ebp+8) 0/r32/eax
31656     # if (!a->is-atom?) a = a->left
31657     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
31658     {
31659       75/jump-if-!= break/disp8
31660       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
31661     }
31662     # return (a->value == stream)
31663     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
31664     0f 94/set-byte-if-= %al
31665     81 4/subop/and %eax 0xff/imm32
31666 $is-mu-stream-type?:end:
31667     # . epilogue
31668     89/<- %esp 5/r32/ebp
31669     5d/pop-to-ebp
31670     c3/return
31671 
31672 test-emit-subx-stmt-primitive:
31673     # Primitive operation on a variable on the stack.
31674     #   increment foo
31675     # =>
31676     #   ff 0/subop/increment *(ebp-8)
31677     #
31678     # There's a variable on the var stack as follows:
31679     #   name: 'foo'
31680     #   type: int
31681     #   stack-offset: -8
31682     #
31683     # There's a primitive with this info:
31684     #   name: 'increment'
31685     #   inouts: int/mem
31686     #   value: 'ff 0/subop/increment'
31687     #
31688     # . prologue
31689     55/push-ebp
31690     89/<- %ebp 4/r32/esp
31691     # setup
31692     (clear-stream _test-output-stream)
31693     (clear-stream $_test-output-buffered-file->buffer)
31694     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
31695 $test-emit-subx-stmt-primitive:initialize-type:
31696     # var type/ecx: (payload type-tree) = int
31697     68/push 0/imm32/right:null
31698     68/push 0/imm32/right:null
31699     68/push 0/imm32/left:unused
31700     68/push 1/imm32/value:int
31701     68/push 1/imm32/is-atom?:true
31702     68/push 0x11/imm32/alloc-id:fake:payload
31703     89/<- %ecx 4/r32/esp
31704 $test-emit-subx-stmt-primitive:initialize-var:
31705     # var var-foo/ecx: (payload var) = var(type)
31706     68/push 0/imm32/no-register
31707     68/push 0/imm32/no-register
31708     68/push -8/imm32/stack-offset
31709     68/push 1/imm32/block-depth
31710     51/push-ecx/type
31711     68/push 0x11/imm32/alloc-id:fake
31712     68/push 0/imm32/name
31713     68/push 0/imm32/name
31714     68/push 0x11/imm32/alloc-id:fake:payload
31715     89/<- %ecx 4/r32/esp
31716 $test-emit-subx-stmt-primitive:initialize-var-name:
31717     # var-foo->name = "foo"
31718     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
31719     (copy-array Heap "foo" %eax)
31720 $test-emit-subx-stmt-primitive:initialize-stmt-var:
31721     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
31722     68/push 0/imm32/is-deref:false
31723     68/push 0/imm32/next
31724     68/push 0/imm32/next
31725     51/push-ecx/var-foo
31726     68/push 0x11/imm32/alloc-id:fake
31727     68/push 0x11/imm32/alloc-id:fake:payload
31728     89/<- %ebx 4/r32/esp
31729 $test-emit-subx-stmt-primitive:initialize-stmt:
31730     # var stmt/esi: (addr statement)
31731     68/push 0/imm32/no-outputs
31732     68/push 0/imm32/no-outputs
31733     53/push-ebx/inouts
31734     68/push 0x11/imm32/alloc-id:fake
31735     68/push 0/imm32/operation
31736     68/push 0/imm32/operation
31737     68/push 1/imm32/tag
31738     89/<- %esi 4/r32/esp
31739 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
31740     # stmt->operation = "increment"
31741     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
31742     (copy-array Heap "increment" %eax)
31743 $test-emit-subx-stmt-primitive:initialize-primitive:
31744     # var primitives/ebx: (addr primitive)
31745     68/push 0/imm32/next
31746     68/push 0/imm32/next
31747     68/push 0/imm32/no-x32
31748     68/push 0/imm32/no-xm32
31749     68/push 0/imm32/no-disp32
31750     68/push 0/imm32/no-imm8
31751     68/push 0/imm32/no-imm32
31752     68/push 0/imm32/no-r32
31753     68/push 1/imm32/rm32-is-first-inout
31754     68/push 0/imm32/subx-name
31755     68/push 0/imm32/subx-name
31756     68/push 0/imm32/no-outputs
31757     68/push 0/imm32/no-outputs
31758     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
31759     68/push 0x11/imm32/alloc-id:fake
31760     68/push 0/imm32/name
31761     68/push 0/imm32/name
31762     89/<- %ebx 4/r32/esp
31763 $test-emit-subx-stmt-primitive:initialize-primitive-name:
31764     # primitives->name = "increment"
31765     (copy-array Heap "increment" %ebx)  # Primitive-name
31766 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
31767     # primitives->subx-name = "ff 0/subop/increment"
31768     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
31769     (copy-array Heap "ff 0/subop/increment" %eax)
31770     # convert
31771     c7 0/subop/copy *Curr-block-depth 0/imm32
31772     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
31773     (flush _test-output-buffered-file)
31774 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
31780     # check output
31781     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
31782     # . epilogue
31783     89/<- %esp 5/r32/ebp
31784     5d/pop-to-ebp
31785     c3/return
31786 
31787 test-emit-subx-stmt-primitive-register:
31788     # Primitive operation on a variable in a register.
31789     #   foo <- increment
31790     # =>
31791     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
31792     #
31793     # There's a variable on the var stack as follows:
31794     #   name: 'foo'
31795     #   type: int
31796     #   register: 'eax'
31797     #
31798     # There's a primitive with this info:
31799     #   name: 'increment'
31800     #   out: int/reg
31801     #   value: 'ff 0/subop/increment'
31802     #
31803     # . prologue
31804     55/push-ebp
31805     89/<- %ebp 4/r32/esp
31806     # setup
31807     (clear-stream _test-output-stream)
31808     (clear-stream $_test-output-buffered-file->buffer)
31809 $test-emit-subx-stmt-primitive-register:initialize-type:
31810     # var type/ecx: (payload type-tree) = int
31811     68/push 0/imm32/right:null
31812     68/push 0/imm32/right:null
31813     68/push 0/imm32/left:unused
31814     68/push 1/imm32/value:int
31815     68/push 1/imm32/is-atom?:true
31816     68/push 0x11/imm32/alloc-id:fake:payload
31817     89/<- %ecx 4/r32/esp
31818 $test-emit-subx-stmt-primitive-register:initialize-var:
31819     # var var-foo/ecx: (payload var)
31820     68/push 0/imm32/register
31821     68/push 0/imm32/register
31822     68/push 0/imm32/no-stack-offset
31823     68/push 1/imm32/block-depth
31824     51/push-ecx
31825     68/push 0x11/imm32/alloc-id:fake
31826     68/push 0/imm32/name
31827     68/push 0/imm32/name
31828     68/push 0x11/imm32/alloc-id:fake:payload
31829     89/<- %ecx 4/r32/esp
31830 $test-emit-subx-stmt-primitive-register:initialize-var-name:
31831     # var-foo->name = "foo"
31832     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
31833     (copy-array Heap "foo" %eax)
31834 $test-emit-subx-stmt-primitive-register:initialize-var-register:
31835     # var-foo->register = "eax"
31836     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
31837     (copy-array Heap "eax" %eax)
31838 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
31839     # var operand/ebx: (payload stmt-var)
31840     68/push 0/imm32/is-deref:false
31841     68/push 0/imm32/next
31842     68/push 0/imm32/next
31843     51/push-ecx/var-foo
31844     68/push 0x11/imm32/alloc-id:fake
31845     68/push 0x11/imm32/alloc-id:fake:payload
31846     89/<- %ebx 4/r32/esp
31847 $test-emit-subx-stmt-primitive-register:initialize-stmt:
31848     # var stmt/esi: (addr statement)
31849     53/push-ebx/outputs
31850     68/push 0x11/imm32/alloc-id:fake
31851     68/push 0/imm32/no-inouts
31852     68/push 0/imm32/no-inouts
31853     68/push 0/imm32/operation
31854     68/push 0/imm32/operation
31855     68/push 1/imm32
31856     89/<- %esi 4/r32/esp
31857 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
31858     # stmt->operation = "increment"
31859     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
31860     (copy-array Heap "increment" %eax)
31861 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
31862     # var formal-var/ebx: (payload var)
31863     68/push 0/imm32/register
31864     68/push 0/imm32/register
31865     68/push 0/imm32/no-stack-offset
31866     68/push 1/imm32/block-depth
31867     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
31868     68/push 0x11/imm32/alloc-id:fake
31869     68/push 0/imm32/name
31870     68/push 0/imm32/name
31871     68/push 0x11/imm32/alloc-id:fake:payload
31872     89/<- %ebx 4/r32/esp
31873 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
31874     # formal-var->name = "dummy"
31875     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
31876     (copy-array Heap "dummy" %eax)
31877 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
31878     # formal-var->register = "*"
31879     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
31880     (copy-array Heap "*" %eax)  # Any-register
31881 $test-emit-subx-stmt-primitive-register:initialize-var-list:
31882     # var formal-outputs/ebx: (payload list var)
31883     68/push 0/imm32/next
31884     68/push 0/imm32/next
31885     53/push-ebx/formal-var
31886     68/push 0x11/imm32/alloc-id:fake
31887     68/push 0x11/imm32/alloc-id:fake:payload
31888     89/<- %ebx 4/r32/esp
31889 $test-emit-subx-stmt-primitive-register:initialize-primitive:
31890     # var primitives/ebx: (addr primitive)
31891     68/push 0/imm32/next
31892     68/push 0/imm32/next
31893     68/push 0/imm32/no-x32
31894     68/push 0/imm32/no-xm32
31895     68/push 0/imm32/no-disp32
31896     68/push 0/imm32/no-imm8
31897     68/push 0/imm32/no-imm32
31898     68/push 0/imm32/no-r32
31899     68/push 3/imm32/rm32-is-first-output
31900     68/push 0/imm32/subx-name
31901     68/push 0/imm32/subx-name
31902     53/push-ebx/outputs
31903     68/push 0x11/imm32/alloc-id:fake
31904     68/push 0/imm32/no-inouts
31905     68/push 0/imm32/no-inouts
31906     68/push 0/imm32/name
31907     68/push 0/imm32/name
31908     89/<- %ebx 4/r32/esp
31909 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
31910     # primitives->name = "increment"
31911     (copy-array Heap "increment" %ebx)  # Primitive-name
31912 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
31913     # primitives->subx-name = "ff 0/subop/increment"
31914     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
31915     (copy-array Heap "ff 0/subop/increment" %eax)
31916     # convert
31917     c7 0/subop/copy *Curr-block-depth 0/imm32
31918     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
31919     (flush _test-output-buffered-file)
31920 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
31926     # check output
31927     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
31928     # . epilogue
31929     89/<- %esp 5/r32/ebp
31930     5d/pop-to-ebp
31931     c3/return
31932 
31933 test-emit-subx-stmt-select-primitive:
31934     # Select the right primitive between overloads.
31935     #   foo <- increment
31936     # =>
31937     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
31938     #
31939     # There's a variable on the var stack as follows:
31940     #   name: 'foo'
31941     #   type: int
31942     #   register: 'eax'
31943     #
31944     # There's two primitives, as follows:
31945     #   - name: 'increment'
31946     #     out: int/reg
31947     #     value: 'ff 0/subop/increment'
31948     #   - name: 'increment'
31949     #     inout: int/mem
31950     #     value: 'ff 0/subop/increment'
31951     #
31952     # . prologue
31953     55/push-ebp
31954     89/<- %ebp 4/r32/esp
31955     # setup
31956     (clear-stream _test-output-stream)
31957     (clear-stream $_test-output-buffered-file->buffer)
31958 $test-emit-subx-stmt-select-primitive:initialize-type:
31959     # var type/ecx: (payload type-tree) = int
31960     68/push 0/imm32/right:null
31961     68/push 0/imm32/right:null
31962     68/push 0/imm32/left:unused
31963     68/push 1/imm32/value:int
31964     68/push 1/imm32/is-atom?:true
31965     68/push 0x11/imm32/alloc-id:fake:payload
31966     89/<- %ecx 4/r32/esp
31967 $test-emit-subx-stmt-select-primitive:initialize-var:
31968     # var var-foo/ecx: (payload var)
31969     68/push 0/imm32/register
31970     68/push 0/imm32/register
31971     68/push 0/imm32/no-stack-offset
31972     68/push 1/imm32/block-depth
31973     51/push-ecx
31974     68/push 0x11/imm32/alloc-id:fake
31975     68/push 0/imm32/name
31976     68/push 0/imm32/name
31977     68/push 0x11/imm32/alloc-id:fake:payload
31978     89/<- %ecx 4/r32/esp
31979 $test-emit-subx-stmt-select-primitive:initialize-var-name:
31980     # var-foo->name = "foo"
31981     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
31982     (copy-array Heap "foo" %eax)
31983 $test-emit-subx-stmt-select-primitive:initialize-var-register:
31984     # var-foo->register = "eax"
31985     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
31986     (copy-array Heap "eax" %eax)
31987 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
31988     # var operand/ebx: (payload stmt-var)
31989     68/push 0/imm32/is-deref:false
31990     68/push 0/imm32/next
31991     68/push 0/imm32/next
31992     51/push-ecx/var-foo
31993     68/push 0x11/imm32/alloc-id:fake
31994     68/push 0x11/imm32/alloc-id:fake:payload
31995     89/<- %ebx 4/r32/esp
31996 $test-emit-subx-stmt-select-primitive:initialize-stmt:
31997     # var stmt/esi: (addr statement)
31998     53/push-ebx/outputs
31999     68/push 0x11/imm32/alloc-id:fake
32000     68/push 0/imm32/no-inouts
32001     68/push 0/imm32/no-inouts
32002     68/push 0/imm32/operation
32003     68/push 0/imm32/operation
32004     68/push 1/imm32
32005     89/<- %esi 4/r32/esp
32006 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
32007     # stmt->operation = "increment"
32008     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32009     (copy-array Heap "increment" %eax)
32010 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
32011     # var formal-var/ebx: (payload var)
32012     68/push 0/imm32/register
32013     68/push 0/imm32/register
32014     68/push 0/imm32/no-stack-offset
32015     68/push 1/imm32/block-depth
32016     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
32017     68/push 0x11/imm32/alloc-id:fake
32018     68/push 0/imm32/name
32019     68/push 0/imm32/name
32020     68/push 0x11/imm32/alloc-id:fake:payload
32021     89/<- %ebx 4/r32/esp
32022 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
32023     # formal-var->name = "dummy"
32024     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
32025     (copy-array Heap "dummy" %eax)
32026 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
32027     # formal-var->register = "*"
32028     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
32029     (copy-array Heap "*" %eax)  # Any-register
32030 $test-emit-subx-stmt-select-primitive:initialize-var-list:
32031     # var formal-outputs/ebx: (payload list var)
32032     68/push 0/imm32/next
32033     68/push 0/imm32/next
32034     53/push-ebx/formal-var
32035     68/push 0x11/imm32/alloc-id:fake
32036     68/push 0x11/imm32/alloc-id:fake:payload
32037     89/<- %ebx 4/r32/esp
32038 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
32039     # var primitive2/edi: (payload primitive)
32040     68/push 0/imm32/next
32041     68/push 0/imm32/next
32042     68/push 0/imm32/no-x32
32043     68/push 0/imm32/no-xm32
32044     68/push 0/imm32/no-disp32
32045     68/push 0/imm32/no-imm8
32046     68/push 0/imm32/no-imm32
32047     68/push 0/imm32/no-r32
32048     68/push 3/imm32/rm32-is-first-output
32049     68/push 0/imm32/subx-name
32050     68/push 0/imm32/subx-name
32051     53/push-ebx/outputs
32052     68/push 0x11/imm32/alloc-id:fake
32053     68/push 0/imm32/no-inouts
32054     68/push 0/imm32/no-inouts
32055     68/push 0/imm32/name
32056     68/push 0/imm32/name
32057     68/push 0x11/imm32/alloc-id:fake:payload
32058     89/<- %edi 4/r32/esp
32059 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
32060     # primitives->name = "increment"
32061     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
32062     (copy-array Heap "increment" %eax)
32063 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
32064     # primitives->subx-name = "ff 0/subop/increment"
32065     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
32066     (copy-array Heap "ff 0/subop/increment" %eax)
32067 $test-emit-subx-stmt-select-primitive:initialize-primitive:
32068     # var primitives/ebx: (addr primitive)
32069     57/push-edi
32070     68/push 0x11/imm32/alloc-id:fake
32071     68/push 0/imm32/no-x32
32072     68/push 0/imm32/no-xm32
32073     68/push 0/imm32/no-disp32
32074     68/push 0/imm32/no-imm8
32075     68/push 0/imm32/no-imm32
32076     68/push 0/imm32/no-r32
32077     68/push 1/imm32/rm32-is-first-inout
32078     68/push 0/imm32/subx-name
32079     68/push 0/imm32/subx-name
32080     68/push 0/imm32/no-outputs
32081     68/push 0/imm32/no-outputs
32082     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
32083     68/push 0x11/imm32/alloc-id:fake
32084     68/push 0/imm32/name
32085     68/push 0/imm32/name
32086     89/<- %ebx 4/r32/esp
32087 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
32088     # primitives->name = "increment"
32089     (copy-array Heap "increment" %ebx)  # Primitive-name
32090 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
32091     # primitives->subx-name = "ff 0/subop/increment"
32092     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
32093     (copy-array Heap "ff 0/subop/increment" %eax)
32094     # convert
32095     c7 0/subop/copy *Curr-block-depth 0/imm32
32096     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
32097     (flush _test-output-buffered-file)
32098 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32104     # check output
32105     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
32106     # . epilogue
32107     89/<- %esp 5/r32/ebp
32108     5d/pop-to-ebp
32109     c3/return
32110 
32111 test-emit-subx-stmt-select-primitive-2:
32112     # Select the right primitive between overloads.
32113     #   increment foo
32114     # =>
32115     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
32116     #
32117     # There's a variable on the var stack as follows:
32118     #   name: 'foo'
32119     #   type: int
32120     #   register: 'eax'
32121     #
32122     # There's two primitives, as follows:
32123     #   - name: 'increment'
32124     #     out: int/reg
32125     #     value: 'ff 0/subop/increment'
32126     #   - name: 'increment'
32127     #     inout: int/mem
32128     #     value: 'ff 0/subop/increment'
32129     #
32130     # . prologue
32131     55/push-ebp
32132     89/<- %ebp 4/r32/esp
32133     # setup
32134     (clear-stream _test-output-stream)
32135     (clear-stream $_test-output-buffered-file->buffer)
32136 $test-emit-subx-stmt-select-primitive-2:initialize-type:
32137     # var type/ecx: (payload type-tree) = int
32138     68/push 0/imm32/right:null
32139     68/push 0/imm32/right:null
32140     68/push 0/imm32/left:unused
32141     68/push 1/imm32/value:int
32142     68/push 1/imm32/is-atom?:true
32143     68/push 0x11/imm32/alloc-id:fake:payload
32144     89/<- %ecx 4/r32/esp
32145 $test-emit-subx-stmt-select-primitive-2:initialize-var:
32146     # var var-foo/ecx: (payload var)
32147     68/push 0/imm32/register
32148     68/push 0/imm32/register
32149     68/push 0/imm32/no-stack-offset
32150     68/push 1/imm32/block-depth
32151     51/push-ecx
32152     68/push 0x11/imm32/alloc-id:fake
32153     68/push 0/imm32/name
32154     68/push 0/imm32/name
32155     68/push 0x11/imm32/alloc-id:fake:payload
32156     89/<- %ecx 4/r32/esp
32157 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
32158     # var-foo->name = "foo"
32159     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32160     (copy-array Heap "foo" %eax)
32161 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
32162     # var-foo->register = "eax"
32163     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32164     (copy-array Heap "eax" %eax)
32165 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
32166     # var operand/ebx: (payload stmt-var)
32167     68/push 0/imm32/is-deref:false
32168     68/push 0/imm32/next
32169     68/push 0/imm32/next
32170     51/push-ecx/var-foo
32171     68/push 0x11/imm32/alloc-id:fake
32172     68/push 0x11/imm32/alloc-id:fake:payload
32173     89/<- %ebx 4/r32/esp
32174 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
32175     # var stmt/esi: (addr statement)
32176     68/push 0/imm32/no-outputs
32177     68/push 0/imm32/no-outputs
32178     53/push-ebx/inouts
32179     68/push 0x11/imm32/alloc-id:fake
32180     68/push 0/imm32/operation
32181     68/push 0/imm32/operation
32182     68/push 1/imm32
32183     89/<- %esi 4/r32/esp
32184 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
32185     # stmt->operation = "increment"
32186     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32187     (copy-array Heap "increment" %eax)
32188 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
32189     # var formal-var/ebx: (payload var)
32190     68/push 0/imm32/register
32191     68/push 0/imm32/register
32192     68/push 0/imm32/no-stack-offset
32193     68/push 1/imm32/block-depth
32194     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
32195     68/push 0x11/imm32/alloc-id:fake
32196     68/push 0/imm32/name
32197     68/push 0/imm32/name
32198     68/push 0x11/imm32/alloc-id:fake:payload
32199     89/<- %ebx 4/r32/esp
32200 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
32201     # formal-var->name = "dummy"
32202     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
32203     (copy-array Heap "dummy" %eax)
32204 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
32205     # formal-var->register = "*"
32206     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
32207     (copy-array Heap "*" %eax)  # Any-register
32208 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
32209     # var formal-outputs/ebx: (payload list stmt-var)
32210     68/push 0/imm32/next
32211     68/push 0/imm32/next
32212     53/push-ebx/formal-var
32213     68/push 0x11/imm32/alloc-id:fake
32214     68/push 0x11/imm32/alloc-id:fake:payload
32215     89/<- %ebx 4/r32/esp
32216 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
32217     # var primitive2/edi: (payload primitive)
32218     68/push 0/imm32/next
32219     68/push 0/imm32/next
32220     68/push 0/imm32/no-x32
32221     68/push 0/imm32/no-xm32
32222     68/push 0/imm32/no-disp32
32223     68/push 0/imm32/no-imm8
32224     68/push 0/imm32/no-imm32
32225     68/push 0/imm32/no-r32
32226     68/push 3/imm32/rm32-is-first-output
32227     68/push 0/imm32/subx-name
32228     68/push 0/imm32/subx-name
32229     53/push-ebx/outputs
32230     68/push 0x11/imm32/alloc-id:fake
32231     68/push 0/imm32/no-inouts
32232     68/push 0/imm32/no-inouts
32233     68/push 0/imm32/name
32234     68/push 0/imm32/name
32235     68/push 0x11/imm32/alloc-id:fake:payload
32236     89/<- %edi 4/r32/esp
32237 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
32238     # primitives->name = "increment"
32239     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
32240     (copy-array Heap "increment" %eax)
32241 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
32242     # primitives->subx-name = "ff 0/subop/increment"
32243     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
32244     (copy-array Heap "ff 0/subop/increment" %eax)
32245 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
32246     # var primitives/ebx: (addr primitive)
32247     57/push-edi
32248     68/push 0x11/imm32/alloc-id:fake
32249     68/push 0/imm32/no-x32
32250     68/push 0/imm32/no-xm32
32251     68/push 0/imm32/no-disp32
32252     68/push 0/imm32/no-imm8
32253     68/push 0/imm32/no-imm32
32254     68/push 0/imm32/no-r32
32255     68/push 1/imm32/rm32-is-first-inout
32256     68/push 0/imm32/subx-name
32257     68/push 0/imm32/subx-name
32258     68/push 0/imm32/no-outputs
32259     68/push 0/imm32/no-outputs
32260     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
32261     68/push 0x11/imm32/alloc-id:fake
32262     68/push 0/imm32/name
32263     68/push 0/imm32/name
32264     89/<- %ebx 4/r32/esp
32265 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
32266     # primitives->name = "increment"
32267     (copy-array Heap "increment" %ebx)  # Primitive-name
32268 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
32269     # primitives->subx-name = "ff 0/subop/increment"
32270     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
32271     (copy-array Heap "ff 0/subop/increment" %eax)
32272     # convert
32273     c7 0/subop/copy *Curr-block-depth 0/imm32
32274     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
32275     (flush _test-output-buffered-file)
32276 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32282     # check output
32283     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
32284     # . epilogue
32285     89/<- %esp 5/r32/ebp
32286     5d/pop-to-ebp
32287     c3/return
32288 
32289 test-increment-register:
32290     # Select the right register between overloads.
32291     #   foo <- increment
32292     # =>
32293     #   50/increment-eax
32294     #
32295     # There's a variable on the var stack as follows:
32296     #   name: 'foo'
32297     #   type: int
32298     #   register: 'eax'
32299     #
32300     # Primitives are the global definitions.
32301     #
32302     # . prologue
32303     55/push-ebp
32304     89/<- %ebp 4/r32/esp
32305     # setup
32306     (clear-stream _test-output-stream)
32307     (clear-stream $_test-output-buffered-file->buffer)
32308 $test-increment-register:initialize-type:
32309     # var type/ecx: (payload type-tree) = int
32310     68/push 0/imm32/right:null
32311     68/push 0/imm32/right:null
32312     68/push 0/imm32/left:unused
32313     68/push 1/imm32/value:int
32314     68/push 1/imm32/is-atom?:true
32315     68/push 0x11/imm32/alloc-id:fake:payload
32316     89/<- %ecx 4/r32/esp
32317 $test-increment-register:initialize-var:
32318     # var var-foo/ecx: (payload var)
32319     68/push 0/imm32/register
32320     68/push 0/imm32/register
32321     68/push 0/imm32/no-stack-offset
32322     68/push 1/imm32/block-depth
32323     51/push-ecx
32324     68/push 0x11/imm32/alloc-id:fake
32325     68/push 0/imm32/name
32326     68/push 0/imm32/name
32327     68/push 0x11/imm32/alloc-id:fake:payload
32328     89/<- %ecx 4/r32/esp
32329 $test-increment-register:initialize-var-name:
32330     # var-foo->name = "foo"
32331     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32332     (copy-array Heap "foo" %eax)
32333 $test-increment-register:initialize-var-register:
32334     # var-foo->register = "eax"
32335     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32336     (copy-array Heap "eax" %eax)
32337 $test-increment-register:initialize-stmt-var:
32338     # var operand/ebx: (payload stmt-var)
32339     68/push 0/imm32/is-deref:false
32340     68/push 0/imm32/next
32341     68/push 0/imm32/next
32342     51/push-ecx/var-foo
32343     68/push 0x11/imm32/alloc-id:fake
32344     68/push 0x11/imm32/alloc-id:fake:payload
32345     89/<- %ebx 4/r32/esp
32346 $test-increment-register:initialize-stmt:
32347     # var stmt/esi: (addr statement)
32348     53/push-ebx/outputs
32349     68/push 0x11/imm32/alloc-id:fake
32350     68/push 0/imm32/no-inouts
32351     68/push 0/imm32/no-inouts
32352     68/push 0/imm32/operation
32353     68/push 0/imm32/operation
32354     68/push 1/imm32
32355     89/<- %esi 4/r32/esp
32356 $test-increment-register:initialize-stmt-operation:
32357     # stmt->operation = "increment"
32358     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32359     (copy-array Heap "increment" %eax)
32360     # convert
32361     c7 0/subop/copy *Curr-block-depth 0/imm32
32362     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
32363     (flush _test-output-buffered-file)
32364 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32370     # check output
32371     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
32372     # . epilogue
32373     89/<- %esp 5/r32/ebp
32374     5d/pop-to-ebp
32375     c3/return
32376 
32377 test-add-reg-to-reg:
32378     #   var1/reg <- add var2/reg
32379     # =>
32380     #   01/add-to %var1 var2
32381     #
32382     # . prologue
32383     55/push-ebp
32384     89/<- %ebp 4/r32/esp
32385     # setup
32386     (clear-stream _test-output-stream)
32387     (clear-stream $_test-output-buffered-file->buffer)
32388 $test-add-reg-to-reg:initialize-type:
32389     # var type/ecx: (payload type-tree) = int
32390     68/push 0/imm32/right:null
32391     68/push 0/imm32/right:null
32392     68/push 0/imm32/left:unused
32393     68/push 1/imm32/value:int
32394     68/push 1/imm32/is-atom?:true
32395     68/push 0x11/imm32/alloc-id:fake:payload
32396     89/<- %ecx 4/r32/esp
32397 $test-add-reg-to-reg:initialize-var1:
32398     # var var1/ecx: (payload var)
32399     68/push 0/imm32/register
32400     68/push 0/imm32/register
32401     68/push 0/imm32/no-stack-offset
32402     68/push 1/imm32/block-depth
32403     51/push-ecx
32404     68/push 0x11/imm32/alloc-id:fake
32405     68/push 0/imm32/name
32406     68/push 0/imm32/name
32407     68/push 0x11/imm32/alloc-id:fake:payload
32408     89/<- %ecx 4/r32/esp
32409 $test-add-reg-to-reg:initialize-var1-name:
32410     # var1->name = "var1"
32411     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32412     (copy-array Heap "var1" %eax)
32413 $test-add-reg-to-reg:initialize-var1-register:
32414     # var1->register = "eax"
32415     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32416     (copy-array Heap "eax" %eax)
32417 $test-add-reg-to-reg:initialize-var2:
32418     # var var2/edx: (payload var)
32419     68/push 0/imm32/register
32420     68/push 0/imm32/register
32421     68/push 0/imm32/no-stack-offset
32422     68/push 1/imm32/block-depth
32423     ff 6/subop/push *(ecx+0x10)
32424     68/push 0x11/imm32/alloc-id:fake
32425     68/push 0/imm32/name
32426     68/push 0/imm32/name
32427     68/push 0x11/imm32/alloc-id:fake:payload
32428     89/<- %edx 4/r32/esp
32429 $test-add-reg-to-reg:initialize-var2-name:
32430     # var2->name = "var2"
32431     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
32432     (copy-array Heap "var2" %eax)
32433 $test-add-reg-to-reg:initialize-var2-register:
32434     # var2->register = "ecx"
32435     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
32436     (copy-array Heap "ecx" %eax)
32437 $test-add-reg-to-reg:initialize-inouts:
32438     # var inouts/esi: (payload stmt-var) = [var2]
32439     68/push 0/imm32/is-deref:false
32440     68/push 0/imm32/next
32441     68/push 0/imm32/next
32442     52/push-edx/var2
32443     68/push 0x11/imm32/alloc-id:fake
32444     68/push 0x11/imm32/alloc-id:fake:payload
32445     89/<- %esi 4/r32/esp
32446 $test-add-reg-to-reg:initialize-outputs:
32447     # var outputs/edi: (payload stmt-var) = [var1]
32448     68/push 0/imm32/is-deref:false
32449     68/push 0/imm32/next
32450     68/push 0/imm32/next
32451     51/push-ecx/var1
32452     68/push 0x11/imm32/alloc-id:fake
32453     68/push 0x11/imm32/alloc-id:fake:payload
32454     89/<- %edi 4/r32/esp
32455 $test-add-reg-to-reg:initialize-stmt:
32456     # var stmt/esi: (addr statement)
32457     68/push 0/imm32/next
32458     68/push 0/imm32/next
32459     57/push-edi/outputs
32460     68/push 0x11/imm32/alloc-id:fake
32461     56/push-esi/inouts
32462     68/push 0x11/imm32/alloc-id:fake
32463     68/push 0/imm32/operation
32464     68/push 0/imm32/operation
32465     68/push 1/imm32/tag:stmt1
32466     89/<- %esi 4/r32/esp
32467 $test-add-reg-to-reg:initialize-stmt-operation:
32468     # stmt->operation = "add"
32469     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32470     (copy-array Heap "add" %eax)
32471     # convert
32472     c7 0/subop/copy *Curr-block-depth 0/imm32
32473     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
32474     (flush _test-output-buffered-file)
32475 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32481     # check output
32482     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
32483     # . epilogue
32484     89/<- %esp 5/r32/ebp
32485     5d/pop-to-ebp
32486     c3/return
32487 
32488 test-add-reg-to-mem:
32489     #   add-to var1 var2/reg
32490     # =>
32491     #   01/add-to *(ebp+__) var2
32492     #
32493     # . prologue
32494     55/push-ebp
32495     89/<- %ebp 4/r32/esp
32496     # setup
32497     (clear-stream _test-output-stream)
32498     (clear-stream $_test-output-buffered-file->buffer)
32499 $test-add-reg-to-mem:initialize-type:
32500     # var type/ecx: (payload type-tree) = int
32501     68/push 0/imm32/right:null
32502     68/push 0/imm32/right:null
32503     68/push 0/imm32/left:unused
32504     68/push 1/imm32/value:int
32505     68/push 1/imm32/is-atom?:true
32506     68/push 0x11/imm32/alloc-id:fake:payload
32507     89/<- %ecx 4/r32/esp
32508 $test-add-reg-to-mem:initialize-var1:
32509     # var var1/ecx: (payload var)
32510     68/push 0/imm32/register
32511     68/push 0/imm32/register
32512     68/push 8/imm32/stack-offset
32513     68/push 1/imm32/block-depth
32514     51/push-ecx
32515     68/push 0x11/imm32/alloc-id:fake
32516     68/push 0/imm32/name
32517     68/push 0/imm32/name
32518     68/push 0x11/imm32/alloc-id:fake:payload
32519     89/<- %ecx 4/r32/esp
32520 $test-add-reg-to-mem:initialize-var1-name:
32521     # var1->name = "var1"
32522     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32523     (copy-array Heap "var1" %eax)
32524 $test-add-reg-to-mem:initialize-var2:
32525     # var var2/edx: (payload var)
32526     68/push 0/imm32/register
32527     68/push 0/imm32/register
32528     68/push 0/imm32/no-stack-offset
32529     68/push 1/imm32/block-depth
32530     ff 6/subop/push *(ecx+0x10)
32531     68/push 0x11/imm32/alloc-id:fake
32532     68/push 0/imm32/name
32533     68/push 0/imm32/name
32534     68/push 0x11/imm32/alloc-id:fake:payload
32535     89/<- %edx 4/r32/esp
32536 $test-add-reg-to-mem:initialize-var2-name:
32537     # var2->name = "var2"
32538     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
32539     (copy-array Heap "var2" %eax)
32540 $test-add-reg-to-mem:initialize-var2-register:
32541     # var2->register = "ecx"
32542     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
32543     (copy-array Heap "ecx" %eax)
32544 $test-add-reg-to-mem:initialize-inouts:
32545     # var inouts/esi: (payload stmt-var) = [var2]
32546     68/push 0/imm32/is-deref:false
32547     68/push 0/imm32/next
32548     68/push 0/imm32/next
32549     52/push-edx/var2
32550     68/push 0x11/imm32/alloc-id:fake
32551     68/push 0x11/imm32/alloc-id:fake:payload
32552     89/<- %esi 4/r32/esp
32553     # inouts = [var1, var2]
32554     68/push 0/imm32/is-deref:false
32555     56/push-esi/next
32556     68/push 0x11/imm32/alloc-id:fake
32557     51/push-ecx/var1
32558     68/push 0x11/imm32/alloc-id:fake
32559     68/push 0x11/imm32/alloc-id:fake:payload
32560     89/<- %esi 4/r32/esp
32561 $test-add-reg-to-mem:initialize-stmt:
32562     # var stmt/esi: (addr statement)
32563     68/push 0/imm32/next
32564     68/push 0/imm32/next
32565     68/push 0/imm32/outputs
32566     68/push 0/imm32/outputs
32567     56/push-esi/inouts
32568     68/push 0x11/imm32/alloc-id:fake
32569     68/push 0/imm32/operation
32570     68/push 0/imm32/operation
32571     68/push 1/imm32/tag:stmt1
32572     89/<- %esi 4/r32/esp
32573 $test-add-reg-to-mem:initialize-stmt-operation:
32574     # stmt->operation = "add-to"
32575     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32576     (copy-array Heap "add-to" %eax)
32577     # convert
32578     c7 0/subop/copy *Curr-block-depth 0/imm32
32579     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
32580     (flush _test-output-buffered-file)
32581 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32587     # check output
32588     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
32589     # . epilogue
32590     89/<- %esp 5/r32/ebp
32591     5d/pop-to-ebp
32592     c3/return
32593 
32594 test-add-mem-to-reg:
32595     #   var1/reg <- add var2
32596     # =>
32597     #   03/add *(ebp+__) var1
32598     #
32599     # . prologue
32600     55/push-ebp
32601     89/<- %ebp 4/r32/esp
32602     # setup
32603     (clear-stream _test-output-stream)
32604     (clear-stream $_test-output-buffered-file->buffer)
32605 $test-add-mem-to-reg:initialize-type:
32606     # var type/ecx: (payload type-tree) = int
32607     68/push 0/imm32/right:null
32608     68/push 0/imm32/right:null
32609     68/push 0/imm32/left:unused
32610     68/push 1/imm32/value:int
32611     68/push 1/imm32/is-atom?:true
32612     68/push 0x11/imm32/alloc-id:fake:payload
32613     89/<- %ecx 4/r32/esp
32614 $test-add-mem-to-reg:initialize-var:
32615     # var var1/ecx: (payload var)
32616     68/push 0/imm32/register
32617     68/push 0/imm32/register
32618     68/push 0/imm32/no-stack-offset
32619     68/push 1/imm32/block-depth
32620     51/push-ecx
32621     68/push 0x11/imm32/alloc-id:fake
32622     68/push 0/imm32/name
32623     68/push 0/imm32/name
32624     68/push 0x11/imm32/alloc-id:fake:payload
32625     89/<- %ecx 4/r32/esp
32626 $test-add-mem-to-reg:initialize-var-name:
32627     # var1->name = "foo"
32628     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32629     (copy-array Heap "var1" %eax)
32630 $test-add-mem-to-reg:initialize-var-register:
32631     # var1->register = "eax"
32632     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32633     (copy-array Heap "eax" %eax)
32634 $test-add-mem-to-reg:initialize-var2:
32635     # var var2/edx: (payload var)
32636     68/push 0/imm32/register
32637     68/push 0/imm32/register
32638     68/push 8/imm32/stack-offset
32639     68/push 1/imm32/block-depth
32640     ff 6/subop/push *(ecx+0x10)
32641     68/push 0x11/imm32/alloc-id:fake
32642     68/push 0/imm32/name
32643     68/push 0/imm32/name
32644     68/push 0x11/imm32/alloc-id:fake:payload
32645     89/<- %edx 4/r32/esp
32646 $test-add-mem-to-reg:initialize-var2-name:
32647     # var2->name = "var2"
32648     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
32649     (copy-array Heap "var2" %eax)
32650 $test-add-mem-to-reg:initialize-inouts:
32651     # var inouts/esi: (payload stmt-var) = [var2]
32652     68/push 0/imm32/is-deref:false
32653     68/push 0/imm32/next
32654     68/push 0/imm32/next
32655     52/push-edx/var2
32656     68/push 0x11/imm32/alloc-id:fake
32657     68/push 0x11/imm32/alloc-id:fake:payload
32658     89/<- %esi 4/r32/esp
32659 $test-add-mem-to-reg:initialize-outputs:
32660     # var outputs/edi: (payload stmt-var) = [var1]
32661     68/push 0/imm32/is-deref:false
32662     68/push 0/imm32/next
32663     68/push 0/imm32/next
32664     51/push-ecx/var1
32665     68/push 0x11/imm32/alloc-id:fake
32666     68/push 0x11/imm32/alloc-id:fake:payload
32667     89/<- %edi 4/r32/esp
32668 $test-add-mem-to-reg:initialize-stmt:
32669     # var stmt/esi: (addr statement)
32670     68/push 0/imm32/next
32671     68/push 0/imm32/next
32672     57/push-edi/outputs
32673     68/push 0x11/imm32/alloc-id:fake
32674     56/push-esi/inouts
32675     68/push 0x11/imm32/alloc-id:fake
32676     68/push 0/imm32/operation
32677     68/push 0/imm32/operation
32678     68/push 1/imm32/tag:stmt1
32679     89/<- %esi 4/r32/esp
32680 $test-add-mem-to-reg:initialize-stmt-operation:
32681     # stmt->operation = "add"
32682     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32683     (copy-array Heap "add" %eax)
32684     # convert
32685     c7 0/subop/copy *Curr-block-depth 0/imm32
32686     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
32687     (flush _test-output-buffered-file)
32688 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32694     # check output
32695     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
32696     # . epilogue
32697     89/<- %esp 5/r32/ebp
32698     5d/pop-to-ebp
32699     c3/return
32700 
32701 test-add-literal-to-eax:
32702     #   var1/eax <- add 0x34
32703     # =>
32704     #   05/add-to-eax 0x34/imm32
32705     #
32706     # . prologue
32707     55/push-ebp
32708     89/<- %ebp 4/r32/esp
32709     # setup
32710     (clear-stream _test-output-stream)
32711     (clear-stream $_test-output-buffered-file->buffer)
32712 $test-add-literal-to-eax:initialize-var-type:
32713     # var type/ecx: (payload type-tree) = int
32714     68/push 0/imm32/right:null
32715     68/push 0/imm32/right:null
32716     68/push 0/imm32/left:unused
32717     68/push 1/imm32/value:int
32718     68/push 1/imm32/is-atom?:true
32719     68/push 0x11/imm32/alloc-id:fake:payload
32720     89/<- %ecx 4/r32/esp
32721 $test-add-literal-to-eax:initialize-var:
32722     # var v/ecx: (payload var)
32723     68/push 0/imm32/register
32724     68/push 0/imm32/register
32725     68/push 0/imm32/no-stack-offset
32726     68/push 1/imm32/block-depth
32727     51/push-ecx
32728     68/push 0x11/imm32/alloc-id:fake
32729     68/push 0/imm32/name
32730     68/push 0/imm32/name
32731     68/push 0x11/imm32/alloc-id:fake:payload
32732     89/<- %ecx 4/r32/esp
32733 $test-add-literal-to-eax:initialize-var-name:
32734     # v->name = "v"
32735     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32736     (copy-array Heap "v" %eax)
32737 $test-add-literal-to-eax:initialize-var-register:
32738     # v->register = "eax"
32739     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32740     (copy-array Heap "eax" %eax)
32741 $test-add-literal-to-eax:initialize-literal-type:
32742     # var type/edx: (payload type-tree) = literal
32743     68/push 0/imm32/right:null
32744     68/push 0/imm32/right:null
32745     68/push 0/imm32/left:unused
32746     68/push 0/imm32/value:literal
32747     68/push 1/imm32/is-atom?:true
32748     68/push 0x11/imm32/alloc-id:fake:payload
32749     89/<- %edx 4/r32/esp
32750 $test-add-literal-to-eax:initialize-literal:
32751     # var l/edx: (payload var)
32752     68/push 0/imm32/register
32753     68/push 0/imm32/register
32754     68/push 0/imm32/no-stack-offset
32755     68/push 1/imm32/block-depth
32756     52/push-edx
32757     68/push 0x11/imm32/alloc-id:fake
32758     68/push 0/imm32/name
32759     68/push 0/imm32/name
32760     68/push 0x11/imm32/alloc-id:fake:payload
32761     89/<- %edx 4/r32/esp
32762 $test-add-literal-to-eax:initialize-literal-value:
32763     # l->name = "0x34"
32764     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
32765     (copy-array Heap "0x34" %eax)
32766 $test-add-literal-to-eax:initialize-inouts:
32767     # var inouts/esi: (payload stmt-var) = [l]
32768     68/push 0/imm32/is-deref:false
32769     68/push 0/imm32/next
32770     68/push 0/imm32/next
32771     52/push-edx/l
32772     68/push 0x11/imm32/alloc-id:fake
32773     68/push 0x11/imm32/alloc-id:fake:payload
32774     89/<- %esi 4/r32/esp
32775 $test-add-literal-to-eax:initialize-outputs:
32776     # var outputs/edi: (payload stmt-var) = [v]
32777     68/push 0/imm32/is-deref:false
32778     68/push 0/imm32/next
32779     68/push 0/imm32/next
32780     51/push-ecx/v
32781     68/push 0x11/imm32/alloc-id:fake
32782     68/push 0x11/imm32/alloc-id:fake:payload
32783     89/<- %edi 4/r32/esp
32784 $test-add-literal-to-eax:initialize-stmt:
32785     # var stmt/esi: (addr statement)
32786     68/push 0/imm32/next
32787     68/push 0/imm32/next
32788     57/push-edi/outputs
32789     68/push 0x11/imm32/alloc-id:fake
32790     56/push-esi/inouts
32791     68/push 0x11/imm32/alloc-id:fake
32792     68/push 0/imm32/operation
32793     68/push 0/imm32/operation
32794     68/push 1/imm32/tag:stmt1
32795     89/<- %esi 4/r32/esp
32796 $test-add-literal-to-eax:initialize-stmt-operation:
32797     # stmt->operation = "add"
32798     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32799     (copy-array Heap "add" %eax)
32800     # convert
32801     c7 0/subop/copy *Curr-block-depth 0/imm32
32802     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
32803     (flush _test-output-buffered-file)
32804 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32810     # check output
32811     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
32812     # . epilogue
32813     89/<- %esp 5/r32/ebp
32814     5d/pop-to-ebp
32815     c3/return
32816 
32817 test-add-literal-to-reg:
32818     #   var1/ecx <- add 0x34
32819     # =>
32820     #   81 0/subop/add %ecx 0x34/imm32
32821     #
32822     # . prologue
32823     55/push-ebp
32824     89/<- %ebp 4/r32/esp
32825     # setup
32826     (clear-stream _test-output-stream)
32827     (clear-stream $_test-output-buffered-file->buffer)
32828 $test-add-literal-to-reg:initialize-var-type:
32829     # var type/ecx: (payload type-tree) = int
32830     68/push 0/imm32/right:null
32831     68/push 0/imm32/right:null
32832     68/push 0/imm32/left:unused
32833     68/push 1/imm32/value:int
32834     68/push 1/imm32/is-atom?:true
32835     68/push 0x11/imm32/alloc-id:fake:payload
32836     89/<- %ecx 4/r32/esp
32837 $test-add-literal-to-reg:initialize-var:
32838     # var v/ecx: (payload var)
32839     68/push 0/imm32/register
32840     68/push 0/imm32/register
32841     68/push 0/imm32/no-stack-offset
32842     68/push 1/imm32/block-depth
32843     51/push-ecx
32844     68/push 0x11/imm32/alloc-id:fake
32845     68/push 0/imm32/name
32846     68/push 0/imm32/name
32847     68/push 0x11/imm32/alloc-id:fake:payload
32848     89/<- %ecx 4/r32/esp
32849 $test-add-literal-to-reg:initialize-var-name:
32850     # v->name = "v"
32851     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32852     (copy-array Heap "v" %eax)
32853 $test-add-literal-to-reg:initialize-var-register:
32854     # v->register = "ecx"
32855     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32856     (copy-array Heap "ecx" %eax)
32857 $test-add-literal-to-reg:initialize-literal-type:
32858     # var type/edx: (payload type-tree) = literal
32859     68/push 0/imm32/right:null
32860     68/push 0/imm32/right:null
32861     68/push 0/imm32/left:unused
32862     68/push 0/imm32/value:literal
32863     68/push 1/imm32/is-atom?:true
32864     68/push 0x11/imm32/alloc-id:fake:payload
32865     89/<- %edx 4/r32/esp
32866 $test-add-literal-to-reg:initialize-literal:
32867     # var l/edx: (payload var)
32868     68/push 0/imm32/register
32869     68/push 0/imm32/register
32870     68/push 0/imm32/no-stack-offset
32871     68/push 1/imm32/block-depth
32872     52/push-edx
32873     68/push 0x11/imm32/alloc-id:fake
32874     68/push 0/imm32/name
32875     68/push 0/imm32/name
32876     68/push 0x11/imm32/alloc-id:fake:payload
32877     89/<- %edx 4/r32/esp
32878 $test-add-literal-to-reg:initialize-literal-value:
32879     # l->name = "0x34"
32880     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
32881     (copy-array Heap "0x34" %eax)
32882 $test-add-literal-to-reg:initialize-inouts:
32883     # var inouts/esi: (payload stmt-var) = [l]
32884     68/push 0/imm32/is-deref:false
32885     68/push 0/imm32/next
32886     68/push 0/imm32/next
32887     52/push-edx/l
32888     68/push 0x11/imm32/alloc-id:fake
32889     68/push 0x11/imm32/alloc-id:fake:payload
32890     89/<- %esi 4/r32/esp
32891 $test-add-literal-to-reg:initialize-outputs:
32892     # var outputs/edi: (payload stmt-var) = [v]
32893     68/push 0/imm32/is-deref:false
32894     68/push 0/imm32/next
32895     68/push 0/imm32/next
32896     51/push-ecx/v
32897     68/push 0x11/imm32/alloc-id:fake
32898     68/push 0x11/imm32/alloc-id:fake:payload
32899     89/<- %edi 4/r32/esp
32900 $test-add-literal-to-reg:initialize-stmt:
32901     # var stmt/esi: (addr statement)
32902     68/push 0/imm32/next
32903     68/push 0/imm32/next
32904     57/push-edi/outputs
32905     68/push 0x11/imm32/alloc-id:fake
32906     56/push-esi/inouts
32907     68/push 0x11/imm32/alloc-id:fake
32908     68/push 0/imm32/operation
32909     68/push 0/imm32/operation
32910     68/push 1/imm32/tag:stmt1
32911     89/<- %esi 4/r32/esp
32912 $test-add-literal-to-reg:initialize-stmt-operation:
32913     # stmt->operation = "add"
32914     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32915     (copy-array Heap "add" %eax)
32916     # convert
32917     c7 0/subop/copy *Curr-block-depth 0/imm32
32918     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
32919     (flush _test-output-buffered-file)
32920 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
32926     # check output
32927     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
32928     # . epilogue
32929     89/<- %esp 5/r32/ebp
32930     5d/pop-to-ebp
32931     c3/return
32932 
32933 test-add-literal-to-mem:
32934     #   add-to var1, 0x34
32935     # =>
32936     #   81 0/subop/add %eax 0x34/imm32
32937     #
32938     # . prologue
32939     55/push-ebp
32940     89/<- %ebp 4/r32/esp
32941     # setup
32942     (clear-stream _test-output-stream)
32943     (clear-stream $_test-output-buffered-file->buffer)
32944 $test-add-literal-to-mem:initialize-type:
32945     # var type/ecx: (payload type-tree) = int
32946     68/push 0/imm32/right:null
32947     68/push 0/imm32/right:null
32948     68/push 0/imm32/left:unused
32949     68/push 1/imm32/value:int
32950     68/push 1/imm32/is-atom?:true
32951     68/push 0x11/imm32/alloc-id:fake:payload
32952     89/<- %ecx 4/r32/esp
32953 $test-add-literal-to-mem:initialize-var1:
32954     # var var1/ecx: (payload var)
32955     68/push 0/imm32/register
32956     68/push 0/imm32/register
32957     68/push 8/imm32/stack-offset
32958     68/push 1/imm32/block-depth
32959     51/push-ecx
32960     68/push 0x11/imm32/alloc-id:fake
32961     68/push 0/imm32/name
32962     68/push 0/imm32/name
32963     68/push 0x11/imm32/alloc-id:fake:payload
32964     89/<- %ecx 4/r32/esp
32965 $test-add-literal-to-mem:initialize-var1-name:
32966     # var1->name = "var1"
32967     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32968     (copy-array Heap "var1" %eax)
32969 $test-add-literal-to-mem:initialize-literal-type:
32970     # var type/edx: (payload type-tree) = literal
32971     68/push 0/imm32/right:null
32972     68/push 0/imm32/right:null
32973     68/push 0/imm32/left:unused
32974     68/push 0/imm32/value:literal
32975     68/push 1/imm32/is-atom?:true
32976     68/push 0x11/imm32/alloc-id:fake:payload
32977     89/<- %edx 4/r32/esp
32978 $test-add-literal-to-mem:initialize-literal:
32979     # var l/edx: (payload var)
32980     68/push 0/imm32/register
32981     68/push 0/imm32/register
32982     68/push 0/imm32/no-stack-offset
32983     68/push 1/imm32/block-depth
32984     52/push-edx
32985     68/push 0x11/imm32/alloc-id:fake
32986     68/push 0/imm32/name
32987     68/push 0/imm32/name
32988     68/push 0x11/imm32/alloc-id:fake:payload
32989     89/<- %edx 4/r32/esp
32990 $test-add-literal-to-mem:initialize-literal-value:
32991     # l->name = "0x34"
32992     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
32993     (copy-array Heap "0x34" %eax)
32994 $test-add-literal-to-mem:initialize-inouts:
32995     # var inouts/esi: (payload stmt-var) = [l]
32996     68/push 0/imm32/is-deref:false
32997     68/push 0/imm32/next
32998     68/push 0/imm32/next
32999     52/push-edx/l
33000     68/push 0x11/imm32/alloc-id:fake
33001     68/push 0x11/imm32/alloc-id:fake:payload
33002     89/<- %esi 4/r32/esp
33003     # var inouts = (handle stmt-var) = [var1, var2]
33004     68/push 0/imm32/is-deref:false
33005     56/push-esi/next
33006     68/push 0x11/imm32/alloc-id:fake
33007     51/push-ecx/var1
33008     68/push 0x11/imm32/alloc-id:fake
33009     68/push 0x11/imm32/alloc-id:fake:payload
33010     89/<- %esi 4/r32/esp
33011 $test-add-literal-to-mem:initialize-stmt:
33012     # var stmt/esi: (addr statement)
33013     68/push 0/imm32/next
33014     68/push 0/imm32/next
33015     68/push 0/imm32/outputs
33016     68/push 0/imm32/outputs
33017     56/push-esi/inouts
33018     68/push 0x11/imm32/alloc-id:fake
33019     68/push 0/imm32/operation
33020     68/push 0/imm32/operation
33021     68/push 1/imm32/tag:stmt1
33022     89/<- %esi 4/r32/esp
33023 $test-add-literal-to-mem:initialize-stmt-operation:
33024     # stmt->operation = "add-to"
33025     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33026     (copy-array Heap "add-to" %eax)
33027     # convert
33028     c7 0/subop/copy *Curr-block-depth 0/imm32
33029     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33030     (flush _test-output-buffered-file)
33031 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33037     # check output
33038     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
33039     # . epilogue
33040     89/<- %esp 5/r32/ebp
33041     5d/pop-to-ebp
33042     c3/return
33043 
33044 test-shift-reg-by-literal:
33045     #   var1/ecx <- shift-left 2
33046     # =>
33047     #   c1/shift 4/subop/left %ecx 2/imm8
33048     #
33049     # . prologue
33050     55/push-ebp
33051     89/<- %ebp 4/r32/esp
33052     # setup
33053     (clear-stream _test-output-stream)
33054     (clear-stream $_test-output-buffered-file->buffer)
33055 $test-shift-reg-by-literal:initialize-var-type:
33056     # var type/ecx: (payload type-tree) = int
33057     68/push 0/imm32/right:null
33058     68/push 0/imm32/right:null
33059     68/push 0/imm32/left:unused
33060     68/push 1/imm32/value:int
33061     68/push 1/imm32/is-atom?:true
33062     68/push 0x11/imm32/alloc-id:fake:payload
33063     89/<- %ecx 4/r32/esp
33064 $test-shift-reg-by-literal:initialize-var:
33065     # var v/ecx: (payload var)
33066     68/push 0/imm32/register
33067     68/push 0/imm32/register
33068     68/push 0/imm32/no-stack-offset
33069     68/push 1/imm32/block-depth
33070     51/push-ecx
33071     68/push 0x11/imm32/alloc-id:fake
33072     68/push 0/imm32/name
33073     68/push 0/imm32/name
33074     68/push 0x11/imm32/alloc-id:fake:payload
33075     89/<- %ecx 4/r32/esp
33076 $test-shift-reg-by-literal:initialize-var-name:
33077     # v->name = "v"
33078     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33079     (copy-array Heap "v" %eax)
33080 $test-shift-reg-by-literal:initialize-var-register:
33081     # v->register = "ecx"
33082     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33083     (copy-array Heap "ecx" %eax)
33084 $test-shift-reg-by-literal:initialize-literal-type:
33085     # var type/edx: (payload type-tree) = literal
33086     68/push 0/imm32/right:null
33087     68/push 0/imm32/right:null
33088     68/push 0/imm32/left:unused
33089     68/push 0/imm32/value:literal
33090     68/push 1/imm32/is-atom?:true
33091     68/push 0x11/imm32/alloc-id:fake:payload
33092     89/<- %edx 4/r32/esp
33093 $test-shift-reg-by-literal:initialize-literal:
33094     # var l/edx: (payload var)
33095     68/push 0/imm32/register
33096     68/push 0/imm32/register
33097     68/push 0/imm32/no-stack-offset
33098     68/push 1/imm32/block-depth
33099     52/push-edx
33100     68/push 0x11/imm32/alloc-id:fake
33101     68/push 0/imm32/name
33102     68/push 0/imm32/name
33103     68/push 0x11/imm32/alloc-id:fake:payload
33104     89/<- %edx 4/r32/esp
33105 $test-shift-reg-by-literal:initialize-literal-value:
33106     # l->name = "2"
33107     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33108     (copy-array Heap "2" %eax)
33109 $test-shift-reg-by-literal:initialize-inouts:
33110     # var inouts/esi: (payload stmt-var) = [l]
33111     68/push 0/imm32/is-deref:false
33112     68/push 0/imm32/next
33113     68/push 0/imm32/next
33114     52/push-edx/l
33115     68/push 0x11/imm32/alloc-id:fake
33116     68/push 0x11/imm32/alloc-id:fake:payload
33117     89/<- %esi 4/r32/esp
33118 $test-shift-reg-by-literal:initialize-outputs:
33119     # var outputs/edi: (payload stmt-var) = [v]
33120     68/push 0/imm32/is-deref:false
33121     68/push 0/imm32/next
33122     68/push 0/imm32/next
33123     51/push-ecx/v
33124     68/push 0x11/imm32/alloc-id:fake
33125     68/push 0x11/imm32/alloc-id:fake:payload
33126     89/<- %edi 4/r32/esp
33127 $test-shift-reg-by-literal:initialize-stmt:
33128     # var stmt/esi: (addr statement)
33129     68/push 0/imm32/next
33130     68/push 0/imm32/next
33131     57/push-edi/outputs
33132     68/push 0x11/imm32/alloc-id:fake
33133     56/push-esi/inouts
33134     68/push 0x11/imm32/alloc-id:fake
33135     68/push 0/imm32/operation
33136     68/push 0/imm32/operation
33137     68/push 1/imm32/tag:stmt1
33138     89/<- %esi 4/r32/esp
33139 $test-shift-reg-by-literal:initialize-stmt-operation:
33140     # stmt->operation = "shift-left"
33141     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33142     (copy-array Heap "shift-left" %eax)
33143     # convert
33144     c7 0/subop/copy *Curr-block-depth 0/imm32
33145     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33146     (flush _test-output-buffered-file)
33147 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33153     # check output
33154     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
33155     # . epilogue
33156     89/<- %esp 5/r32/ebp
33157     5d/pop-to-ebp
33158     c3/return
33159 
33160 test-shift-mem-by-literal:
33161     #   shift-left var 3
33162     # =>
33163     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
33164     #
33165     # . prologue
33166     55/push-ebp
33167     89/<- %ebp 4/r32/esp
33168     # setup
33169     (clear-stream _test-output-stream)
33170     (clear-stream $_test-output-buffered-file->buffer)
33171 $test-shift-mem-by-literal:initialize-type:
33172     # var type/ecx: (payload type-tree) = int
33173     68/push 0/imm32/right:null
33174     68/push 0/imm32/right:null
33175     68/push 0/imm32/left:unused
33176     68/push 1/imm32/value:int
33177     68/push 1/imm32/is-atom?:true
33178     68/push 0x11/imm32/alloc-id:fake:payload
33179     89/<- %ecx 4/r32/esp
33180 $test-shift-mem-by-literal:initialize-var1:
33181     # var var1/ecx: (payload var)
33182     68/push 0/imm32/register
33183     68/push 0/imm32/register
33184     68/push 8/imm32/stack-offset
33185     68/push 1/imm32/block-depth
33186     51/push-ecx
33187     68/push 0x11/imm32/alloc-id:fake
33188     68/push 0/imm32/name
33189     68/push 0/imm32/name
33190     68/push 0x11/imm32/alloc-id:fake:payload
33191     89/<- %ecx 4/r32/esp
33192 $test-shift-mem-by-literal:initialize-var1-name:
33193     # var1->name = "var1"
33194     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33195     (copy-array Heap "var1" %eax)
33196 $test-shift-mem-by-literal:initialize-literal-type:
33197     # var type/edx: (payload type-tree) = literal
33198     68/push 0/imm32/right:null
33199     68/push 0/imm32/right:null
33200     68/push 0/imm32/left:unused
33201     68/push 0/imm32/value:literal
33202     68/push 1/imm32/is-atom?:true
33203     68/push 0x11/imm32/alloc-id:fake:payload
33204     89/<- %edx 4/r32/esp
33205 $test-shift-mem-by-literal:initialize-literal:
33206     # var l/edx: (payload var)
33207     68/push 0/imm32/register
33208     68/push 0/imm32/register
33209     68/push 0/imm32/no-stack-offset
33210     68/push 1/imm32/block-depth
33211     52/push-edx
33212     68/push 0x11/imm32/alloc-id:fake
33213     68/push 0/imm32/name
33214     68/push 0/imm32/name
33215     68/push 0x11/imm32/alloc-id:fake:payload
33216     89/<- %edx 4/r32/esp
33217 $test-shift-mem-by-literal:initialize-literal-value:
33218     # l->name = "3"
33219     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33220     (copy-array Heap "3" %eax)
33221 $test-shift-mem-by-literal:initialize-inouts:
33222     # var inouts/esi: (payload stmt-var) = [l]
33223     68/push 0/imm32/is-deref:false
33224     68/push 0/imm32/next
33225     68/push 0/imm32/next
33226     52/push-edx/l
33227     68/push 0x11/imm32/alloc-id:fake
33228     68/push 0x11/imm32/alloc-id:fake:payload
33229     89/<- %esi 4/r32/esp
33230     # var inouts = (handle stmt-var) = [var1, var2]
33231     68/push 0/imm32/is-deref:false
33232     56/push-esi/next
33233     68/push 0x11/imm32/alloc-id:fake
33234     51/push-ecx/var1
33235     68/push 0x11/imm32/alloc-id:fake
33236     68/push 0x11/imm32/alloc-id:fake:payload
33237     89/<- %esi 4/r32/esp
33238 $test-shift-mem-by-literal:initialize-stmt:
33239     # var stmt/esi: (addr statement)
33240     68/push 0/imm32/next
33241     68/push 0/imm32/next
33242     68/push 0/imm32/outputs
33243     68/push 0/imm32/outputs
33244     56/push-esi/inouts
33245     68/push 0x11/imm32/alloc-id:fake
33246     68/push 0/imm32/operation
33247     68/push 0/imm32/operation
33248     68/push 1/imm32/tag:stmt1
33249     89/<- %esi 4/r32/esp
33250 $test-shift-mem-by-literal:initialize-stmt-operation:
33251     # stmt->operation = "shift-left"
33252     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33253     (copy-array Heap "shift-left" %eax)
33254     # convert
33255     c7 0/subop/copy *Curr-block-depth 0/imm32
33256     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33257     (flush _test-output-buffered-file)
33258 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33264     # check output
33265     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
33266     # . epilogue
33267     89/<- %esp 5/r32/ebp
33268     5d/pop-to-ebp
33269     c3/return
33270 
33271 test-compare-reg-with-reg:
33272     #   compare var1/ecx, var2/eax
33273     # =>
33274     #   39/compare %ecx 0/r32/eax
33275     #
33276     # . prologue
33277     55/push-ebp
33278     89/<- %ebp 4/r32/esp
33279     # setup
33280     (clear-stream _test-output-stream)
33281     (clear-stream $_test-output-buffered-file->buffer)
33282 $test-compare-reg-with-reg:initialize-type:
33283     # var type/ecx: (payload type-tree) = int
33284     68/push 0/imm32/right:null
33285     68/push 0/imm32/right:null
33286     68/push 0/imm32/left:unused
33287     68/push 1/imm32/value:int
33288     68/push 1/imm32/is-atom?:true
33289     68/push 0x11/imm32/alloc-id:fake:payload
33290     89/<- %ecx 4/r32/esp
33291 $test-compare-reg-with-reg:initialize-var1:
33292     # var var1/ecx: (payload var)
33293     68/push 0/imm32/register
33294     68/push 0/imm32/register
33295     68/push 0/imm32/no-stack-offset
33296     68/push 1/imm32/block-depth
33297     51/push-ecx
33298     68/push 0x11/imm32/alloc-id:fake
33299     68/push 0/imm32/name
33300     68/push 0/imm32/name
33301     68/push 0x11/imm32/alloc-id:fake:payload
33302     89/<- %ecx 4/r32/esp
33303 $test-compare-reg-with-reg:initialize-var1-name:
33304     # var1->name = "var1"
33305     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33306     (copy-array Heap "var1" %eax)
33307 $test-compare-reg-with-reg:initialize-var1-register:
33308     # var1->register = "ecx"
33309     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33310     (copy-array Heap "ecx" %eax)
33311 $test-compare-reg-with-reg:initialize-var2:
33312     # var var2/edx: (payload var)
33313     68/push 0/imm32/register
33314     68/push 0/imm32/register
33315     68/push 0/imm32/no-stack-offset
33316     68/push 1/imm32/block-depth
33317     ff 6/subop/push *(ecx+0x10)
33318     68/push 0x11/imm32/alloc-id:fake
33319     68/push 0/imm32/name
33320     68/push 0/imm32/name
33321     68/push 0x11/imm32/alloc-id:fake:payload
33322     89/<- %edx 4/r32/esp
33323 $test-compare-reg-with-reg:initialize-var2-name:
33324     # var2->name = "var2"
33325     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33326     (copy-array Heap "var2" %eax)
33327 $test-compare-reg-with-reg:initialize-var2-register:
33328     # var2->register = "eax"
33329     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
33330     (copy-array Heap "eax" %eax)
33331 $test-compare-reg-with-reg:initialize-inouts:
33332     # var inouts/esi: (payload stmt-var) = [var2]
33333     68/push 0/imm32/is-deref:false
33334     68/push 0/imm32/next
33335     68/push 0/imm32/next
33336     52/push-edx/var2
33337     68/push 0x11/imm32/alloc-id:fake
33338     68/push 0x11/imm32/alloc-id:fake:payload
33339     89/<- %esi 4/r32/esp
33340     # inouts = [var1, var2]
33341     68/push 0/imm32/is-deref:false
33342     56/push-esi/next
33343     68/push 0x11/imm32/alloc-id:fake
33344     51/push-ecx/var1
33345     68/push 0x11/imm32/alloc-id:fake
33346     68/push 0x11/imm32/alloc-id:fake:payload
33347     89/<- %esi 4/r32/esp
33348 $test-compare-reg-with-reg:initialize-stmt:
33349     # var stmt/esi: (addr statement)
33350     68/push 0/imm32/next
33351     68/push 0/imm32/next
33352     68/push 0/imm32/outputs
33353     68/push 0/imm32/outputs
33354     56/push-esi/inouts
33355     68/push 0x11/imm32/alloc-id:fake
33356     68/push 0/imm32/operation
33357     68/push 0/imm32/operation
33358     68/push 1/imm32/tag:stmt1
33359     89/<- %esi 4/r32/esp
33360 $test-compare-reg-with-reg:initialize-stmt-operation:
33361     # stmt->operation = "compare"
33362     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33363     (copy-array Heap "compare" %eax)
33364     # convert
33365     c7 0/subop/copy *Curr-block-depth 0/imm32
33366     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33367     (flush _test-output-buffered-file)
33368 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33374     # check output
33375     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
33376     # . epilogue
33377     89/<- %esp 5/r32/ebp
33378     5d/pop-to-ebp
33379     c3/return
33380 
33381 test-compare-mem-with-reg:
33382     #   compare var1, var2/eax
33383     # =>
33384     #   39/compare *(ebp+___) 0/r32/eax
33385     #
33386     # . prologue
33387     55/push-ebp
33388     89/<- %ebp 4/r32/esp
33389     # setup
33390     (clear-stream _test-output-stream)
33391     (clear-stream $_test-output-buffered-file->buffer)
33392 $test-compare-mem-with-reg:initialize-type:
33393     # var type/ecx: (payload type-tree) = int
33394     68/push 0/imm32/right:null
33395     68/push 0/imm32/right:null
33396     68/push 0/imm32/left:unused
33397     68/push 1/imm32/value:int
33398     68/push 1/imm32/is-atom?:true
33399     68/push 0x11/imm32/alloc-id:fake:payload
33400     89/<- %ecx 4/r32/esp
33401 $test-compare-mem-with-reg:initialize-var1:
33402     # var var1/ecx: (payload var)
33403     68/push 0/imm32/register
33404     68/push 0/imm32/register
33405     68/push 8/imm32/stack-offset
33406     68/push 1/imm32/block-depth
33407     51/push-ecx
33408     68/push 0x11/imm32/alloc-id:fake
33409     68/push 0/imm32/name
33410     68/push 0/imm32/name
33411     68/push 0x11/imm32/alloc-id:fake:payload
33412     89/<- %ecx 4/r32/esp
33413 $test-compare-mem-with-reg:initialize-var1-name:
33414     # var1->name = "var1"
33415     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33416     (copy-array Heap "var1" %eax)
33417 $test-compare-mem-with-reg:initialize-var2:
33418     # var var2/edx: (payload var)
33419     68/push 0/imm32/register
33420     68/push 0/imm32/register
33421     68/push 0/imm32/no-stack-offset
33422     68/push 1/imm32/block-depth
33423     ff 6/subop/push *(ecx+0x10)
33424     68/push 0x11/imm32/alloc-id:fake
33425     68/push 0/imm32/name
33426     68/push 0/imm32/name
33427     68/push 0x11/imm32/alloc-id:fake:payload
33428     89/<- %edx 4/r32/esp
33429 $test-compare-mem-with-reg:initialize-var2-name:
33430     # var2->name = "var2"
33431     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33432     (copy-array Heap "var2" %eax)
33433 $test-compare-mem-with-reg:initialize-var2-register:
33434     # var2->register = "eax"
33435     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
33436     (copy-array Heap "eax" %eax)
33437 $test-compare-mem-with-reg:initialize-inouts:
33438     # var inouts/esi: (payload stmt-var) = [var2]
33439     68/push 0/imm32/is-deref:false
33440     68/push 0/imm32/next
33441     68/push 0/imm32/next
33442     52/push-edx/var2
33443     68/push 0x11/imm32/alloc-id:fake
33444     68/push 0x11/imm32/alloc-id:fake:payload
33445     89/<- %esi 4/r32/esp
33446     # inouts = [var1, var2]
33447     68/push 0/imm32/is-deref:false
33448     56/push-esi/next
33449     68/push 0x11/imm32/alloc-id:fake
33450     51/push-ecx/var1
33451     68/push 0x11/imm32/alloc-id:fake
33452     68/push 0x11/imm32/alloc-id:fake:payload
33453     89/<- %esi 4/r32/esp
33454 $test-compare-mem-with-reg:initialize-stmt:
33455     # var stmt/esi: (addr statement)
33456     68/push 0/imm32/next
33457     68/push 0/imm32/next
33458     68/push 0/imm32/outputs
33459     68/push 0/imm32/outputs
33460     56/push-esi/inouts
33461     68/push 0x11/imm32/alloc-id:fake
33462     68/push 0/imm32/operation
33463     68/push 0/imm32/operation
33464     68/push 1/imm32/tag:stmt1
33465     89/<- %esi 4/r32/esp
33466 $test-compare-mem-with-reg:initialize-stmt-operation:
33467     # stmt->operation = "compare"
33468     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33469     (copy-array Heap "compare" %eax)
33470     # convert
33471     c7 0/subop/copy *Curr-block-depth 0/imm32
33472     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33473     (flush _test-output-buffered-file)
33474 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33480     # check output
33481     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
33482     # . epilogue
33483     89/<- %esp 5/r32/ebp
33484     5d/pop-to-ebp
33485     c3/return
33486 
33487 test-compare-reg-with-mem:
33488     #   compare var1/eax, var2
33489     # =>
33490     #   3b/compare<- *(ebp+___) 0/r32/eax
33491     #
33492     # . prologue
33493     55/push-ebp
33494     89/<- %ebp 4/r32/esp
33495     # setup
33496     (clear-stream _test-output-stream)
33497     (clear-stream $_test-output-buffered-file->buffer)
33498 $test-compare-reg-with-mem:initialize-type:
33499     # var type/ecx: (payload type-tree) = int
33500     68/push 0/imm32/right:null
33501     68/push 0/imm32/right:null
33502     68/push 0/imm32/left:unused
33503     68/push 1/imm32/value:int
33504     68/push 1/imm32/is-atom?:true
33505     68/push 0x11/imm32/alloc-id:fake:payload
33506     89/<- %ecx 4/r32/esp
33507 $test-compare-reg-with-mem:initialize-var1:
33508     # var var1/ecx: (payload var)
33509     68/push 0/imm32/register
33510     68/push 0/imm32/register
33511     68/push 0/imm32/no-stack-offset
33512     68/push 1/imm32/block-depth
33513     51/push-ecx
33514     68/push 0x11/imm32/alloc-id:fake
33515     68/push 0/imm32/name
33516     68/push 0/imm32/name
33517     68/push 0x11/imm32/alloc-id:fake:payload
33518     89/<- %ecx 4/r32/esp
33519 $test-compare-reg-with-mem:initialize-var1-name:
33520     # var1->name = "var1"
33521     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33522     (copy-array Heap "var1" %eax)
33523 $test-compare-reg-with-mem:initialize-var1-register:
33524     # var1->register = "eax"
33525     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33526     (copy-array Heap "eax" %eax)
33527 $test-compare-reg-with-mem:initialize-var2:
33528     # var var2/edx: (payload var)
33529     68/push 0/imm32/register
33530     68/push 0/imm32/register
33531     68/push 8/imm32/stack-offset
33532     68/push 1/imm32/block-depth
33533     ff 6/subop/push *(ecx+0x10)
33534     68/push 0x11/imm32/alloc-id:fake
33535     68/push 0/imm32/name
33536     68/push 0/imm32/name
33537     68/push 0x11/imm32/alloc-id:fake:payload
33538     89/<- %edx 4/r32/esp
33539 $test-compare-reg-with-mem:initialize-var2-name:
33540     # var2->name = "var2"
33541     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33542     (copy-array Heap "var2" %eax)
33543 $test-compare-reg-with-mem:initialize-inouts:
33544     # var inouts/esi: (payload stmt-var) = [var2]
33545     68/push 0/imm32/is-deref:false
33546     68/push 0/imm32/next
33547     68/push 0/imm32/next
33548     52/push-edx/var2
33549     68/push 0x11/imm32/alloc-id:fake
33550     68/push 0x11/imm32/alloc-id:fake:payload
33551     89/<- %esi 4/r32/esp
33552     # inouts = [var1, var2]
33553     68/push 0/imm32/is-deref:false
33554     56/push-esi/next
33555     68/push 0x11/imm32/alloc-id:fake
33556     51/push-ecx/var1
33557     68/push 0x11/imm32/alloc-id:fake
33558     68/push 0x11/imm32/alloc-id:fake:payload
33559     89/<- %esi 4/r32/esp
33560 $test-compare-reg-with-mem:initialize-stmt:
33561     # var stmt/esi: (addr statement)
33562     68/push 0/imm32/next
33563     68/push 0/imm32/next
33564     68/push 0/imm32/outputs
33565     68/push 0/imm32/outputs
33566     56/push-esi/inouts
33567     68/push 0x11/imm32/alloc-id:fake
33568     68/push 0/imm32/operation
33569     68/push 0/imm32/operation
33570     68/push 1/imm32/tag:stmt1
33571     89/<- %esi 4/r32/esp
33572 $test-compare-reg-with-mem:initialize-stmt-operation:
33573     # stmt->operation = "compare"
33574     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33575     (copy-array Heap "compare" %eax)
33576     # convert
33577     c7 0/subop/copy *Curr-block-depth 0/imm32
33578     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33579     (flush _test-output-buffered-file)
33580 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33586     # check output
33587     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
33588     # . epilogue
33589     89/<- %esp 5/r32/ebp
33590     5d/pop-to-ebp
33591     c3/return
33592 
33593 test-compare-mem-with-literal:
33594     #   compare var1, 0x34
33595     # =>
33596     #   81 7/subop/compare *(ebp+___) 0x34/imm32
33597     #
33598     # . prologue
33599     55/push-ebp
33600     89/<- %ebp 4/r32/esp
33601     # setup
33602     (clear-stream _test-output-stream)
33603     (clear-stream $_test-output-buffered-file->buffer)
33604 $test-compare-mem-with-literal:initialize-type:
33605     # var type/ecx: (payload type-tree) = int
33606     68/push 0/imm32/right:null
33607     68/push 0/imm32/right:null
33608     68/push 0/imm32/left:unused
33609     68/push 1/imm32/value:int
33610     68/push 1/imm32/is-atom?:true
33611     68/push 0x11/imm32/alloc-id:fake:payload
33612     89/<- %ecx 4/r32/esp
33613 $test-compare-mem-with-literal:initialize-var1:
33614     # var var1/ecx: (payload var)
33615     68/push 0/imm32/register
33616     68/push 0/imm32/register
33617     68/push 8/imm32/stack-offset
33618     68/push 1/imm32/block-depth
33619     51/push-ecx
33620     68/push 0x11/imm32/alloc-id:fake
33621     68/push 0/imm32/name
33622     68/push 0/imm32/name
33623     68/push 0x11/imm32/alloc-id:fake:payload
33624     89/<- %ecx 4/r32/esp
33625 $test-compare-mem-with-literal:initialize-var1-name:
33626     # var1->name = "var1"
33627     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33628     (copy-array Heap "var1" %eax)
33629 $test-compare-mem-with-literal:initialize-literal-type:
33630     # var type/edx: (payload type-tree) = literal
33631     68/push 0/imm32/right:null
33632     68/push 0/imm32/right:null
33633     68/push 0/imm32/left:unused
33634     68/push 0/imm32/value:literal
33635     68/push 1/imm32/is-atom?:true
33636     68/push 0x11/imm32/alloc-id:fake:payload
33637     89/<- %edx 4/r32/esp
33638 $test-compare-mem-with-literal:initialize-literal:
33639     # var l/edx: (payload var)
33640     68/push 0/imm32/register
33641     68/push 0/imm32/register
33642     68/push 0/imm32/no-stack-offset
33643     68/push 1/imm32/block-depth
33644     52/push-edx
33645     68/push 0x11/imm32/alloc-id:fake
33646     68/push 0/imm32/name
33647     68/push 0/imm32/name
33648     68/push 0x11/imm32/alloc-id:fake:payload
33649     89/<- %edx 4/r32/esp
33650 $test-compare-mem-with-literal:initialize-literal-value:
33651     # l->name = "0x34"
33652     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33653     (copy-array Heap "0x34" %eax)
33654 $test-compare-mem-with-literal:initialize-inouts:
33655     # var inouts/esi: (payload stmt-var) = [l]
33656     68/push 0/imm32/is-deref:false
33657     68/push 0/imm32/next
33658     68/push 0/imm32/next
33659     52/push-edx/l
33660     68/push 0x11/imm32/alloc-id:fake
33661     68/push 0x11/imm32/alloc-id:fake:payload
33662     89/<- %esi 4/r32/esp
33663     # var inouts = (handle stmt-var) = [var1, var2]
33664     68/push 0/imm32/is-deref:false
33665     56/push-esi/next
33666     68/push 0x11/imm32/alloc-id:fake
33667     51/push-ecx/var1
33668     68/push 0x11/imm32/alloc-id:fake
33669     68/push 0x11/imm32/alloc-id:fake:payload
33670     89/<- %esi 4/r32/esp
33671 $test-compare-mem-with-literal:initialize-stmt:
33672     # var stmt/esi: (addr statement)
33673     68/push 0/imm32/next
33674     68/push 0/imm32/next
33675     68/push 0/imm32/outputs
33676     68/push 0/imm32/outputs
33677     56/push-esi/inouts
33678     68/push 0x11/imm32/alloc-id:fake
33679     68/push 0/imm32/operation
33680     68/push 0/imm32/operation
33681     68/push 1/imm32/tag:stmt1
33682     89/<- %esi 4/r32/esp
33683 $test-compare-mem-with-literal:initialize-stmt-operation:
33684     # stmt->operation = "compare"
33685     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33686     (copy-array Heap "compare" %eax)
33687     # convert
33688     c7 0/subop/copy *Curr-block-depth 0/imm32
33689     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33690     (flush _test-output-buffered-file)
33691 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33697     # check output
33698     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
33699     # . epilogue
33700     89/<- %esp 5/r32/ebp
33701     5d/pop-to-ebp
33702     c3/return
33703 
33704 test-compare-eax-with-literal:
33705     #   compare var1/eax 0x34
33706     # =>
33707     #   3d/compare-eax-with 0x34/imm32
33708     #
33709     # . prologue
33710     55/push-ebp
33711     89/<- %ebp 4/r32/esp
33712     # setup
33713     (clear-stream _test-output-stream)
33714     (clear-stream $_test-output-buffered-file->buffer)
33715 $test-compare-eax-with-literal:initialize-type:
33716     # var type/ecx: (payload type-tree) = int
33717     68/push 0/imm32/right:null
33718     68/push 0/imm32/right:null
33719     68/push 0/imm32/left:unused
33720     68/push 1/imm32/value:int
33721     68/push 1/imm32/is-atom?:true
33722     68/push 0x11/imm32/alloc-id:fake:payload
33723     89/<- %ecx 4/r32/esp
33724 $test-compare-eax-with-literal:initialize-var1:
33725     # var var1/ecx: (payload var)
33726     68/push 0/imm32/register
33727     68/push 0/imm32/register
33728     68/push 0/imm32/no-stack-offset
33729     68/push 1/imm32/block-depth
33730     51/push-ecx
33731     68/push 0x11/imm32/alloc-id:fake
33732     68/push 0/imm32/name
33733     68/push 0/imm32/name
33734     68/push 0x11/imm32/alloc-id:fake:payload
33735     89/<- %ecx 4/r32/esp
33736 $test-compare-eax-with-literal:initialize-var1-name:
33737     # var1->name = "var1"
33738     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33739     (copy-array Heap "var1" %eax)
33740 $test-compare-eax-with-literal:initialize-var1-register:
33741     # v->register = "eax"
33742     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33743     (copy-array Heap "eax" %eax)
33744 $test-compare-eax-with-literal:initialize-literal-type:
33745     # var type/edx: (payload type-tree) = literal
33746     68/push 0/imm32/right:null
33747     68/push 0/imm32/right:null
33748     68/push 0/imm32/left:unused
33749     68/push 0/imm32/value:literal
33750     68/push 1/imm32/is-atom?:true
33751     68/push 0x11/imm32/alloc-id:fake:payload
33752     89/<- %edx 4/r32/esp
33753 $test-compare-eax-with-literal:initialize-literal:
33754     # var l/edx: (payload var)
33755     68/push 0/imm32/register
33756     68/push 0/imm32/register
33757     68/push 0/imm32/no-stack-offset
33758     68/push 1/imm32/block-depth
33759     52/push-edx
33760     68/push 0x11/imm32/alloc-id:fake
33761     68/push 0/imm32/name
33762     68/push 0/imm32/name
33763     68/push 0x11/imm32/alloc-id:fake:payload
33764     89/<- %edx 4/r32/esp
33765 $test-compare-eax-with-literal:initialize-literal-value:
33766     # l->name = "0x34"
33767     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33768     (copy-array Heap "0x34" %eax)
33769 $test-compare-eax-with-literal:initialize-inouts:
33770     # var inouts/esi: (payload stmt-var) = [l]
33771     68/push 0/imm32/is-deref:false
33772     68/push 0/imm32/next
33773     68/push 0/imm32/next
33774     52/push-edx/l
33775     68/push 0x11/imm32/alloc-id:fake
33776     68/push 0x11/imm32/alloc-id:fake:payload
33777     89/<- %esi 4/r32/esp
33778     # var inouts = (handle stmt-var) = [var1, var2]
33779     68/push 0/imm32/is-deref:false
33780     56/push-esi/next
33781     68/push 0x11/imm32/alloc-id:fake
33782     51/push-ecx/var1
33783     68/push 0x11/imm32/alloc-id:fake
33784     68/push 0x11/imm32/alloc-id:fake:payload
33785     89/<- %esi 4/r32/esp
33786 $test-compare-eax-with-literal:initialize-stmt:
33787     # var stmt/esi: (addr statement)
33788     68/push 0/imm32/next
33789     68/push 0/imm32/next
33790     68/push 0/imm32/outputs
33791     68/push 0/imm32/outputs
33792     56/push-esi/inouts
33793     68/push 0x11/imm32/alloc-id:fake
33794     68/push 0/imm32/operation
33795     68/push 0/imm32/operation
33796     68/push 1/imm32/tag:stmt1
33797     89/<- %esi 4/r32/esp
33798 $test-compare-eax-with-literal:initialize-stmt-operation:
33799     # stmt->operation = "compare"
33800     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33801     (copy-array Heap "compare" %eax)
33802     # convert
33803     c7 0/subop/copy *Curr-block-depth 0/imm32
33804     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33805     (flush _test-output-buffered-file)
33806 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33812     # check output
33813     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
33814     # . epilogue
33815     89/<- %esp 5/r32/ebp
33816     5d/pop-to-ebp
33817     c3/return
33818 
33819 test-compare-reg-with-literal:
33820     #   compare var1/ecx 0x34
33821     # =>
33822     #   81 7/subop/compare %ecx 0x34/imm32
33823     #
33824     # . prologue
33825     55/push-ebp
33826     89/<- %ebp 4/r32/esp
33827     # setup
33828     (clear-stream _test-output-stream)
33829     (clear-stream $_test-output-buffered-file->buffer)
33830 $test-compare-reg-with-literal:initialize-type:
33831     # var type/ecx: (payload type-tree) = int
33832     68/push 0/imm32/right:null
33833     68/push 0/imm32/right:null
33834     68/push 0/imm32/left:unused
33835     68/push 1/imm32/value:int
33836     68/push 1/imm32/is-atom?:true
33837     68/push 0x11/imm32/alloc-id:fake:payload
33838     89/<- %ecx 4/r32/esp
33839 $test-compare-reg-with-literal:initialize-var1:
33840     # var var1/ecx: (payload var)
33841     68/push 0/imm32/register
33842     68/push 0/imm32/register
33843     68/push 0/imm32/no-stack-offset
33844     68/push 1/imm32/block-depth
33845     51/push-ecx
33846     68/push 0x11/imm32/alloc-id:fake
33847     68/push 0/imm32/name
33848     68/push 0/imm32/name
33849     68/push 0x11/imm32/alloc-id:fake:payload
33850     89/<- %ecx 4/r32/esp
33851 $test-compare-reg-with-literal:initialize-var1-name:
33852     # var1->name = "var1"
33853     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33854     (copy-array Heap "var1" %eax)
33855 $test-compare-reg-with-literal:initialize-var1-register:
33856     # v->register = "ecx"
33857     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33858     (copy-array Heap "ecx" %eax)
33859 $test-compare-reg-with-literal:initialize-literal-type:
33860     # var type/edx: (payload type-tree) = literal
33861     68/push 0/imm32/right:null
33862     68/push 0/imm32/right:null
33863     68/push 0/imm32/left:unused
33864     68/push 0/imm32/value:literal
33865     68/push 1/imm32/is-atom?:true
33866     68/push 0x11/imm32/alloc-id:fake:payload
33867     89/<- %edx 4/r32/esp
33868 $test-compare-reg-with-literal:initialize-literal:
33869     # var l/edx: (payload var)
33870     68/push 0/imm32/register
33871     68/push 0/imm32/register
33872     68/push 0/imm32/no-stack-offset
33873     68/push 1/imm32/block-depth
33874     52/push-edx
33875     68/push 0x11/imm32/alloc-id:fake
33876     68/push 0/imm32/name
33877     68/push 0/imm32/name
33878     68/push 0x11/imm32/alloc-id:fake:payload
33879     89/<- %edx 4/r32/esp
33880 $test-compare-reg-with-literal:initialize-literal-value:
33881     # l->name = "0x34"
33882     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33883     (copy-array Heap "0x34" %eax)
33884 $test-compare-reg-with-literal:initialize-inouts:
33885     # var inouts/esi: (payload stmt-var) = [l]
33886     68/push 0/imm32/is-deref:false
33887     68/push 0/imm32/next
33888     68/push 0/imm32/next
33889     52/push-edx/l
33890     68/push 0x11/imm32/alloc-id:fake
33891     68/push 0x11/imm32/alloc-id:fake:payload
33892     89/<- %esi 4/r32/esp
33893     # var inouts = (handle stmt-var) = [var1, var2]
33894     68/push 0/imm32/is-deref:false
33895     56/push-esi/next
33896     68/push 0x11/imm32/alloc-id:fake
33897     51/push-ecx/var1
33898     68/push 0x11/imm32/alloc-id:fake
33899     68/push 0x11/imm32/alloc-id:fake:payload
33900     89/<- %esi 4/r32/esp
33901 $test-compare-reg-with-literal:initialize-stmt:
33902     # var stmt/esi: (addr statement)
33903     68/push 0/imm32/next
33904     68/push 0/imm32/next
33905     68/push 0/imm32/outputs
33906     68/push 0/imm32/outputs
33907     56/push-esi/inouts
33908     68/push 0x11/imm32/alloc-id:fake
33909     68/push 0/imm32/operation
33910     68/push 0/imm32/operation
33911     68/push 1/imm32/tag:stmt1
33912     89/<- %esi 4/r32/esp
33913 $test-compare-reg-with-literal:initialize-stmt-operation:
33914     # stmt->operation = "compare"
33915     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33916     (copy-array Heap "compare" %eax)
33917     # convert
33918     c7 0/subop/copy *Curr-block-depth 0/imm32
33919     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33920     (flush _test-output-buffered-file)
33921 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
33927     # check output
33928     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
33929     # . epilogue
33930     89/<- %esp 5/r32/ebp
33931     5d/pop-to-ebp
33932     c3/return
33933 
33934 test-emit-subx-stmt-function-call:
33935     # Call a function on a variable on the stack.
33936     #   f foo
33937     # =>
33938     #   (f *(ebp-8))
33939     # (Changing the function name supports overloading in general, but here it
33940     # just serves to help disambiguate things.)
33941     #
33942     # There's a variable on the var stack as follows:
33943     #   name: 'foo'
33944     #   type: int
33945     #   stack-offset: -8
33946     #
33947     # There's nothing in primitives.
33948     #
33949     # We don't perform any checking here on the type of 'f'.
33950     #
33951     # . prologue
33952     55/push-ebp
33953     89/<- %ebp 4/r32/esp
33954     # setup
33955     (clear-stream _test-output-stream)
33956     (clear-stream $_test-output-buffered-file->buffer)
33957 $test-emit-subx-function-call:initialize-type:
33958     # var type/ecx: (payload type-tree) = int
33959     68/push 0/imm32/right:null
33960     68/push 0/imm32/right:null
33961     68/push 0/imm32/left:unused
33962     68/push 1/imm32/value:int
33963     68/push 1/imm32/is-atom?:true
33964     68/push 0x11/imm32/alloc-id:fake:payload
33965     89/<- %ecx 4/r32/esp
33966 $test-emit-subx-function-call:initialize-var:
33967     # var var-foo/ecx: (payload var) = var(type)
33968     68/push 0/imm32/no-register
33969     68/push 0/imm32/no-register
33970     68/push -8/imm32/stack-offset
33971     68/push 1/imm32/block-depth
33972     51/push-ecx/type
33973     68/push 0x11/imm32/alloc-id:fake
33974     68/push 0/imm32/name
33975     68/push 0/imm32/name
33976     68/push 0x11/imm32/alloc-id:fake:payload
33977     89/<- %ecx 4/r32/esp
33978 $test-emit-subx-function-call:initialize-var-name:
33979     # var-foo->name = "foo"
33980     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33981     (copy-array Heap "foo" %eax)
33982 $test-emit-subx-function-call:initialize-stmt-var:
33983     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
33984     68/push 0/imm32/is-deref:false
33985     68/push 0/imm32/next
33986     68/push 0/imm32/next
33987     51/push-ecx/var-foo
33988     68/push 0x11/imm32/alloc-id:fake
33989     68/push 0x11/imm32/alloc-id:fake:payload
33990     89/<- %ebx 4/r32/esp
33991 $test-emit-subx-function-call:initialize-stmt:
33992     # var stmt/esi: (addr statement)
33993     68/push 0/imm32/no-outputs
33994     68/push 0/imm32/no-outputs
33995     53/push-ebx/inouts
33996     68/push 0x11/imm32/alloc-id:fake
33997     68/push 0/imm32/operation
33998     68/push 0/imm32/operation
33999     68/push 1/imm32/tag
34000     89/<- %esi 4/r32/esp
34001 $test-emit-subx-function-call:initialize-stmt-operation:
34002     # stmt->operation = "f"
34003     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34004     (copy-array Heap "f" %eax)
34005     # convert
34006     c7 0/subop/copy *Curr-block-depth 0/imm32
34007     (emit-subx-stmt _test-output-buffered-file %esi 0 Stderr 0)
34008     (flush _test-output-buffered-file)
34009 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
34015     # check output
34016     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
34017     # . epilogue
34018     89/<- %esp 5/r32/ebp
34019     5d/pop-to-ebp
34020     c3/return
34021 
34022 test-emit-subx-stmt-function-call-with-literal-arg:
34023     # Call a function on a literal.
34024     #   f 0x34
34025     # =>
34026     #   (f2 0x34)
34027     #
34028     # . prologue
34029     55/push-ebp
34030     89/<- %ebp 4/r32/esp
34031     # setup
34032     (clear-stream _test-output-stream)
34033     (clear-stream $_test-output-buffered-file->buffer)
34034 $test-emit-subx-function-call-with-literal-arg:initialize-type:
34035     # var type/ecx: (payload type-tree) = int
34036     68/push 0/imm32/right:null
34037     68/push 0/imm32/right:null
34038     68/push 0/imm32/left:unused
34039     68/push 0/imm32/value:literal
34040     68/push 1/imm32/is-atom?:true
34041     68/push 0x11/imm32/alloc-id:fake:payload
34042     89/<- %ecx 4/r32/esp
34043 $test-emit-subx-function-call-with-literal-arg:initialize-var:
34044     # var var-foo/ecx: (payload var) = var(lit)
34045     68/push 0/imm32/no-register
34046     68/push 0/imm32/no-register
34047     68/push 0/imm32/no-stack-offset
34048     68/push 1/imm32/block-depth
34049     51/push-ecx/type
34050     68/push 0x11/imm32/alloc-id:fake
34051     68/push 0/imm32/name
34052     68/push 0/imm32/name
34053     68/push 0x11/imm32/alloc-id:fake:payload
34054     89/<- %ecx 4/r32/esp
34055 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
34056     # var-foo->name = "0x34"
34057     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34058     (copy-array Heap "0x34" %eax)
34059 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
34060     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
34061     68/push 0/imm32/is-deref:false
34062     68/push 0/imm32/next
34063     68/push 0/imm32/next
34064     51/push-ecx/var-foo
34065     68/push 0x11/imm32/alloc-id:fake
34066     68/push 0x11/imm32/alloc-id:fake:payload
34067     89/<- %ebx 4/r32/esp
34068 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
34069     # var stmt/esi: (addr statement)
34070     68/push 0/imm32/no-outputs
34071     68/push 0/imm32/no-outputs
34072     53/push-ebx/inouts
34073     68/push 0x11/imm32/alloc-id:fake
34074     68/push 0/imm32/operation
34075     68/push 0/imm32/operation
34076     68/push 1/imm32/tag
34077     89/<- %esi 4/r32/esp
34078 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
34079     # stmt->operation = "f"
34080     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34081     (copy-array Heap "f" %eax)
34082     # convert
34083     c7 0/subop/copy *Curr-block-depth 0/imm32
34084     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx Stderr 0)
34085     (flush _test-output-buffered-file)
34086 +--  6 lines: #?     # dump _test-output-stream ------------------------------------------------------------------------------------------------------------------------------------------------------------------
34092     # check output
34093     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
34094     # . epilogue
34095     89/<- %esp 5/r32/ebp
34096     5d/pop-to-ebp
34097     c3/return
34098 
34099 emit-indent:  # out: (addr buffered-file), n: int
34100     # . prologue
34101     55/push-ebp
34102     89/<- %ebp 4/r32/esp
34103     # . save registers
34104     50/push-eax
34105     # var i/eax: int = n
34106     8b/-> *(ebp+0xc) 0/r32/eax
34107     {
34108       # if (i <= 0) break
34109       3d/compare-eax-with 0/imm32
34110       7e/jump-if-<= break/disp8
34111       (write-buffered *(ebp+8) "  ")
34112       48/decrement-eax
34113       eb/jump loop/disp8
34114     }
34115 $emit-indent:end:
34116     # . restore registers
34117     58/pop-to-eax
34118     # . epilogue
34119     89/<- %esp 5/r32/ebp
34120     5d/pop-to-ebp
34121     c3/return
34122 
34123 emit-subx-prologue:  # out: (addr buffered-file)
34124     # . prologue
34125     55/push-ebp
34126     89/<- %ebp 4/r32/esp
34127     #
34128     (write-buffered *(ebp+8) "  # . prologue\n")
34129     (write-buffered *(ebp+8) "  55/push-ebp\n")
34130     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
34131 $emit-subx-prologue:end:
34132     # . epilogue
34133     89/<- %esp 5/r32/ebp
34134     5d/pop-to-ebp
34135     c3/return
34136 
34137 emit-subx-epilogue:  # out: (addr buffered-file)
34138     # . prologue
34139     55/push-ebp
34140     89/<- %ebp 4/r32/esp
34141     #
34142     (write-buffered *(ebp+8) "  # . epilogue\n")
34143     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
34144     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
34145     (write-buffered *(ebp+8) "  c3/return\n")
34146 $emit-subx-epilogue:end:
34147     # . epilogue
34148     89/<- %esp 5/r32/ebp
34149     5d/pop-to-ebp
34150     c3/return