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   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484     # if (argv[1] == "test') run-tests()
  485     {
  486       # if (argc <= 1) break
  487       81 7/subop/compare *ebp 1/imm32
  488       7e/jump-if-<= break/disp8
  489       # if (argv[1] != "test") break
  490       (kernel-string-equal? *(ebp+8) "test")  # => eax
  491       3d/compare-eax-and 0/imm32/false
  492       74/jump-if-= break/disp8
  493       #
  494       (run-tests)
  495       # syscall(exit, *Num-test-failures)
  496       8b/-> *Num-test-failures 3/r32/ebx
  497       eb/jump $mu-main:end/disp8
  498     }
  499     # otherwise convert Stdin
  500     (convert-mu Stdin Stdout Stderr 0)
  501     (flush Stdout)
  502     # syscall(exit, 0)
  503     bb/copy-to-ebx 0/imm32
  504 $mu-main:end:
  505     e8/call syscall_exit/disp32
  506 
  507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  508     # . prologue
  509     55/push-ebp
  510     89/<- %ebp 4/r32/esp
  511     # . save registers
  512     50/push-eax
  513     # initialize global data structures
  514     c7 0/subop/copy *Next-block-index 1/imm32
  515     8b/-> *Primitive-type-ids 0/r32/eax
  516     89/<- *Type-id 0/r32/eax  # stream-write
  517     c7 0/subop/copy *_Program-functions 0/imm32
  518     c7 0/subop/copy *_Program-functions->payload 0/imm32
  519     c7 0/subop/copy *_Program-types 0/imm32
  520     c7 0/subop/copy *_Program-types->payload 0/imm32
  521     c7 0/subop/copy *_Program-signatures 0/imm32
  522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  523     #
  524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  526 #?     (dump-typeinfos "=== typeinfos\n")
  527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  529 $convert-mu:end:
  530     # . restore registers
  531     58/pop-to-eax
  532     # . epilogue
  533     89/<- %esp 5/r32/ebp
  534     5d/pop-to-ebp
  535     c3/return
  536 
  537 test-convert-empty-input:
  538     # empty input => empty output
  539     # . prologue
  540     55/push-ebp
  541     89/<- %ebp 4/r32/esp
  542     # setup
  543     (clear-stream _test-input-stream)
  544     (clear-stream $_test-input-buffered-file->buffer)
  545     (clear-stream _test-output-stream)
  546     (clear-stream $_test-output-buffered-file->buffer)
  547     #
  548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  549     (flush _test-output-buffered-file)
  550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  551     # . epilogue
  552     89/<- %esp 5/r32/ebp
  553     5d/pop-to-ebp
  554     c3/return
  555 
  556 test-convert-function-skeleton:
  557     # . prologue
  558     55/push-ebp
  559     89/<- %ebp 4/r32/esp
  560     # setup
  561     (clear-stream _test-input-stream)
  562     (clear-stream $_test-input-buffered-file->buffer)
  563     (clear-stream _test-output-stream)
  564     (clear-stream $_test-output-buffered-file->buffer)
  565     #
  566     (write _test-input-stream "fn foo {\n")
  567     (write _test-input-stream "}\n")
  568     # convert
  569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  570     (flush _test-output-buffered-file)
  571 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  577     # check output
  578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  586     # . epilogue
  587     89/<- %esp 5/r32/ebp
  588     5d/pop-to-ebp
  589     c3/return
  590 
  591 test-convert-multiple-function-skeletons:
  592     # . prologue
  593     55/push-ebp
  594     89/<- %ebp 4/r32/esp
  595     # setup
  596     (clear-stream _test-input-stream)
  597     (clear-stream $_test-input-buffered-file->buffer)
  598     (clear-stream _test-output-stream)
  599     (clear-stream $_test-output-buffered-file->buffer)
  600     #
  601     (write _test-input-stream "fn foo {\n")
  602     (write _test-input-stream "}\n")
  603     (write _test-input-stream "fn bar {\n")
  604     (write _test-input-stream "}\n")
  605     # convert
  606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  607     (flush _test-output-buffered-file)
  608 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  614     # check first function
  615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  623     # check second function
  624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  632     # . epilogue
  633     89/<- %esp 5/r32/ebp
  634     5d/pop-to-ebp
  635     c3/return
  636 
  637 test-convert-function-with-arg:
  638     # . prologue
  639     55/push-ebp
  640     89/<- %ebp 4/r32/esp
  641     # setup
  642     (clear-stream _test-input-stream)
  643     (clear-stream $_test-input-buffered-file->buffer)
  644     (clear-stream _test-output-stream)
  645     (clear-stream $_test-output-buffered-file->buffer)
  646     #
  647     (write _test-input-stream "fn foo n: int {\n")
  648     (write _test-input-stream "}\n")
  649     # convert
  650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  651     (flush _test-output-buffered-file)
  652 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  658     # check output
  659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  667     # . epilogue
  668     89/<- %esp 5/r32/ebp
  669     5d/pop-to-ebp
  670     c3/return
  671 
  672 test-function-with-redefined-name:
  673     # . prologue
  674     55/push-ebp
  675     89/<- %ebp 4/r32/esp
  676     # setup
  677     (clear-stream _test-input-stream)
  678     (clear-stream $_test-input-buffered-file->buffer)
  679     (clear-stream _test-output-stream)
  680     (clear-stream $_test-output-buffered-file->buffer)
  681     (clear-stream _test-error-stream)
  682     (clear-stream $_test-error-buffered-file->buffer)
  683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  684     68/push 0/imm32
  685     68/push 0/imm32
  686     89/<- %edx 4/r32/esp
  687     (tailor-exit-descriptor %edx 0x10)
  688     #
  689     (write _test-input-stream "fn foo {\n")
  690     (write _test-input-stream "}\n")
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     # convert
  694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  695     # registers except esp clobbered at this point
  696     # restore ed
  697     89/<- %edx 4/r32/esp
  698     (flush _test-output-buffered-file)
  699     (flush _test-error-buffered-file)
  700 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  706     # check output
  707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  709     # check that stop(1) was called
  710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  711     # don't restore from ebp
  712     81 0/subop/add %esp 8/imm32
  713     # . epilogue
  714     5d/pop-to-ebp
  715     c3/return
  716 
  717 test-function-with-redefined-name-2:
  718     # . prologue
  719     55/push-ebp
  720     89/<- %ebp 4/r32/esp
  721     # setup
  722     (clear-stream _test-input-stream)
  723     (clear-stream $_test-input-buffered-file->buffer)
  724     (clear-stream _test-output-stream)
  725     (clear-stream $_test-output-buffered-file->buffer)
  726     (clear-stream _test-error-stream)
  727     (clear-stream $_test-error-buffered-file->buffer)
  728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  729     68/push 0/imm32
  730     68/push 0/imm32
  731     89/<- %edx 4/r32/esp
  732     (tailor-exit-descriptor %edx 0x10)
  733     #
  734     (write _test-input-stream "fn foo {\n")
  735     (write _test-input-stream "}\n")
  736     (write _test-input-stream "sig foo\n")
  737     # convert
  738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  739     # registers except esp clobbered at this point
  740     # restore ed
  741     89/<- %edx 4/r32/esp
  742     (flush _test-output-buffered-file)
  743     (flush _test-error-buffered-file)
  744 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  750     # check output
  751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  753     # check that stop(1) was called
  754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  755     # don't restore from ebp
  756     81 0/subop/add %esp 8/imm32
  757     # . epilogue
  758     5d/pop-to-ebp
  759     c3/return
  760 
  761 test-function-with-redefined-name-3:
  762     # . prologue
  763     55/push-ebp
  764     89/<- %ebp 4/r32/esp
  765     # setup
  766     (clear-stream _test-input-stream)
  767     (clear-stream $_test-input-buffered-file->buffer)
  768     (clear-stream _test-output-stream)
  769     (clear-stream $_test-output-buffered-file->buffer)
  770     (clear-stream _test-error-stream)
  771     (clear-stream $_test-error-buffered-file->buffer)
  772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  773     68/push 0/imm32
  774     68/push 0/imm32
  775     89/<- %edx 4/r32/esp
  776     (tailor-exit-descriptor %edx 0x10)
  777     #
  778     (write _test-input-stream "sig foo\n")
  779     (write _test-input-stream "fn foo {\n")
  780     (write _test-input-stream "}\n")
  781     # convert
  782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  783     # registers except esp clobbered at this point
  784     # restore ed
  785     89/<- %edx 4/r32/esp
  786     (flush _test-output-buffered-file)
  787     (flush _test-error-buffered-file)
  788 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  794     # check output
  795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  797     # check that stop(1) was called
  798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  799     # don't restore from ebp
  800     81 0/subop/add %esp 8/imm32
  801     # . epilogue
  802     5d/pop-to-ebp
  803     c3/return
  804 
  805 test-function-with-inout-in-register:
  806     # . prologue
  807     55/push-ebp
  808     89/<- %ebp 4/r32/esp
  809     # setup
  810     (clear-stream _test-input-stream)
  811     (clear-stream $_test-input-buffered-file->buffer)
  812     (clear-stream _test-output-stream)
  813     (clear-stream $_test-output-buffered-file->buffer)
  814     (clear-stream _test-error-stream)
  815     (clear-stream $_test-error-buffered-file->buffer)
  816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  817     68/push 0/imm32
  818     68/push 0/imm32
  819     89/<- %edx 4/r32/esp
  820     (tailor-exit-descriptor %edx 0x10)
  821     #
  822     (write _test-input-stream "fn foo x/eax: int {\n")
  823     (write _test-input-stream "}\n")
  824     # convert
  825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  826     # registers except esp clobbered at this point
  827     # restore ed
  828     89/<- %edx 4/r32/esp
  829     (flush _test-output-buffered-file)
  830     (flush _test-error-buffered-file)
  831 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  837     # check output
  838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  839     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  840     # check that stop(1) was called
  841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  842     # don't restore from ebp
  843     81 0/subop/add %esp 8/imm32
  844     # . epilogue
  845     5d/pop-to-ebp
  846     c3/return
  847 
  848 test-convert-function-with-arg-and-body:
  849     # . prologue
  850     55/push-ebp
  851     89/<- %ebp 4/r32/esp
  852     # setup
  853     (clear-stream _test-input-stream)
  854     (clear-stream $_test-input-buffered-file->buffer)
  855     (clear-stream _test-output-stream)
  856     (clear-stream $_test-output-buffered-file->buffer)
  857     #
  858     (write _test-input-stream "fn foo n: int {\n")
  859     (write _test-input-stream "  increment n\n")
  860     (write _test-input-stream "}\n")
  861     # convert
  862     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  863     (flush _test-output-buffered-file)
  864 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  870     # check output
  871     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
  872     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
  873     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
  874     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
  875     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
  876     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
  877     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
  878     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
  879     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
  880     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
  881     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
  882     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
  883     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
  884     # . epilogue
  885     89/<- %esp 5/r32/ebp
  886     5d/pop-to-ebp
  887     c3/return
  888 
  889 test-convert-function-distinguishes-args:
  890     # . prologue
  891     55/push-ebp
  892     89/<- %ebp 4/r32/esp
  893     # setup
  894     (clear-stream _test-input-stream)
  895     (clear-stream $_test-input-buffered-file->buffer)
  896     (clear-stream _test-output-stream)
  897     (clear-stream $_test-output-buffered-file->buffer)
  898     #
  899     (write _test-input-stream "fn foo a: int, b: int {\n")
  900     (write _test-input-stream "  increment b\n")
  901     (write _test-input-stream "}\n")
  902     # convert
  903     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  904     (flush _test-output-buffered-file)
  905 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  911     # check output
  912     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
  913     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
  914     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
  915     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
  916     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
  917     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
  918     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
  919     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
  920     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
  921     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
  922     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
  923     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
  924     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
  925     # . epilogue
  926     89/<- %esp 5/r32/ebp
  927     5d/pop-to-ebp
  928     c3/return
  929 
  930 test-convert-function-with-return-literal:
  931     # . prologue
  932     55/push-ebp
  933     89/<- %ebp 4/r32/esp
  934     # setup
  935     (clear-stream _test-input-stream)
  936     (clear-stream $_test-input-buffered-file->buffer)
  937     (clear-stream _test-output-stream)
  938     (clear-stream $_test-output-buffered-file->buffer)
  939     #
  940     (write _test-input-stream "fn foo -> _/eax: int {\n")
  941     (write _test-input-stream "  return 0\n")
  942     (write _test-input-stream "}\n")
  943     # convert
  944     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  945     (flush _test-output-buffered-file)
  946 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  952     # check output
  953     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
  954     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
  955     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
  956     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
  957     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
  958     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
  959     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
  960     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
  961     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
  962     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
  963     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
  964     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
  965     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
  966     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
  967     # . epilogue
  968     89/<- %esp 5/r32/ebp
  969     5d/pop-to-ebp
  970     c3/return
  971 
  972 test-convert-function-with-return:
  973     # . prologue
  974     55/push-ebp
  975     89/<- %ebp 4/r32/esp
  976     # setup
  977     (clear-stream _test-input-stream)
  978     (clear-stream $_test-input-buffered-file->buffer)
  979     (clear-stream _test-output-stream)
  980     (clear-stream $_test-output-buffered-file->buffer)
  981     #
  982     (write _test-input-stream "fn foo -> _/eax: int {\n")
  983     (write _test-input-stream "  var y: int\n")
  984     (write _test-input-stream "  return y\n")
  985     (write _test-input-stream "}\n")
  986     # convert
  987     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  988     (flush _test-output-buffered-file)
  989 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  995     # check output
  996     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
  997     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
  998     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
  999     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1000     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1001     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1002     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1003     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1004     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1005     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1006     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1007     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1009     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1011     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1012     # . epilogue
 1013     89/<- %esp 5/r32/ebp
 1014     5d/pop-to-ebp
 1015     c3/return
 1016 
 1017 test-convert-function-with-return-register:
 1018     # . prologue
 1019     55/push-ebp
 1020     89/<- %ebp 4/r32/esp
 1021     # setup
 1022     (clear-stream _test-input-stream)
 1023     (clear-stream $_test-input-buffered-file->buffer)
 1024     (clear-stream _test-output-stream)
 1025     (clear-stream $_test-output-buffered-file->buffer)
 1026     #
 1027     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1028     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1029     (write _test-input-stream "  return y\n")
 1030     (write _test-input-stream "}\n")
 1031     # convert
 1032     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1033     (flush _test-output-buffered-file)
 1034 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1040     # check output
 1041     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1042     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1043     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1044     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1045     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1046     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1047     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1048     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1049     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1050     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1051     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1052     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1053     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1054     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1055     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1056     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1057     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1058     # . epilogue
 1059     89/<- %esp 5/r32/ebp
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 test-function-with-output-without-register:
 1064     # . prologue
 1065     55/push-ebp
 1066     89/<- %ebp 4/r32/esp
 1067     # setup
 1068     (clear-stream _test-input-stream)
 1069     (clear-stream $_test-input-buffered-file->buffer)
 1070     (clear-stream _test-output-stream)
 1071     (clear-stream $_test-output-buffered-file->buffer)
 1072     (clear-stream _test-error-stream)
 1073     (clear-stream $_test-error-buffered-file->buffer)
 1074     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1075     68/push 0/imm32
 1076     68/push 0/imm32
 1077     89/<- %edx 4/r32/esp
 1078     (tailor-exit-descriptor %edx 0x10)
 1079     #
 1080     (write _test-input-stream "fn foo -> _: int {\n")
 1081     (write _test-input-stream "}\n")
 1082     # convert
 1083     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1084     # registers except esp clobbered at this point
 1085     # restore ed
 1086     89/<- %edx 4/r32/esp
 1087     (flush _test-output-buffered-file)
 1088     (flush _test-error-buffered-file)
 1089 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1095     # check output
 1096     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1097     (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")
 1098     # check that stop(1) was called
 1099     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1100     # don't restore from ebp
 1101     81 0/subop/add %esp 8/imm32
 1102     # . epilogue
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-function-with-outputs-in-conflicting-registers:
 1107     # . prologue
 1108     55/push-ebp
 1109     89/<- %ebp 4/r32/esp
 1110     # setup
 1111     (clear-stream _test-input-stream)
 1112     (clear-stream $_test-input-buffered-file->buffer)
 1113     (clear-stream _test-output-stream)
 1114     (clear-stream $_test-output-buffered-file->buffer)
 1115     (clear-stream _test-error-stream)
 1116     (clear-stream $_test-error-buffered-file->buffer)
 1117     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1118     68/push 0/imm32
 1119     68/push 0/imm32
 1120     89/<- %edx 4/r32/esp
 1121     (tailor-exit-descriptor %edx 0x10)
 1122     #
 1123     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1124     (write _test-input-stream "}\n")
 1125     # convert
 1126     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1127     # registers except esp clobbered at this point
 1128     # restore ed
 1129     89/<- %edx 4/r32/esp
 1130     (flush _test-output-buffered-file)
 1131     (flush _test-error-buffered-file)
 1132 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1138     # check output
 1139     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1140     (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")
 1141     # check that stop(1) was called
 1142     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1143     # don't restore from ebp
 1144     81 0/subop/add %esp 8/imm32
 1145     # . epilogue
 1146     5d/pop-to-ebp
 1147     c3/return
 1148 
 1149 test-function-with-named-output:
 1150     # . prologue
 1151     55/push-ebp
 1152     89/<- %ebp 4/r32/esp
 1153     # setup
 1154     (clear-stream _test-input-stream)
 1155     (clear-stream $_test-input-buffered-file->buffer)
 1156     (clear-stream _test-output-stream)
 1157     (clear-stream $_test-output-buffered-file->buffer)
 1158     (clear-stream _test-error-stream)
 1159     (clear-stream $_test-error-buffered-file->buffer)
 1160     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1161     68/push 0/imm32
 1162     68/push 0/imm32
 1163     89/<- %edx 4/r32/esp
 1164     (tailor-exit-descriptor %edx 0x10)
 1165     #
 1166     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1167     (write _test-input-stream "  return 0\n")
 1168     (write _test-input-stream "}\n")
 1169     # convert
 1170     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1171     # registers except esp clobbered at this point
 1172     # restore ed
 1173     89/<- %edx 4/r32/esp
 1174     (flush _test-output-buffered-file)
 1175     (flush _test-error-buffered-file)
 1176 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1182     # check output
 1183     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1184     (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")
 1185     # check that stop(1) was called
 1186     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1187     # don't restore from ebp
 1188     81 0/subop/add %esp 8/imm32
 1189     # . epilogue
 1190     5d/pop-to-ebp
 1191     c3/return
 1192 
 1193 test-return-with-wrong-type:
 1194     # . prologue
 1195     55/push-ebp
 1196     89/<- %ebp 4/r32/esp
 1197     # setup
 1198     (clear-stream _test-input-stream)
 1199     (clear-stream $_test-input-buffered-file->buffer)
 1200     (clear-stream _test-output-stream)
 1201     (clear-stream $_test-output-buffered-file->buffer)
 1202     (clear-stream _test-error-stream)
 1203     (clear-stream $_test-error-buffered-file->buffer)
 1204     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1205     68/push 0/imm32
 1206     68/push 0/imm32
 1207     89/<- %edx 4/r32/esp
 1208     (tailor-exit-descriptor %edx 0x10)
 1209     #
 1210     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1211     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1212     (write _test-input-stream "  return x\n")
 1213     (write _test-input-stream "}\n")
 1214     # convert
 1215     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1216     # registers except esp clobbered at this point
 1217     # restore ed
 1218     89/<- %edx 4/r32/esp
 1219     (flush _test-output-buffered-file)
 1220     (flush _test-error-buffered-file)
 1221 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1227     # check output
 1228     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1229     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1230     # check that stop(1) was called
 1231     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1232     # don't restore from ebp
 1233     81 0/subop/add %esp 8/imm32
 1234     # . epilogue
 1235     5d/pop-to-ebp
 1236     c3/return
 1237 
 1238 test-missing-return:
 1239     # . prologue
 1240     55/push-ebp
 1241     89/<- %ebp 4/r32/esp
 1242     # setup
 1243     (clear-stream _test-input-stream)
 1244     (clear-stream $_test-input-buffered-file->buffer)
 1245     (clear-stream _test-output-stream)
 1246     (clear-stream $_test-output-buffered-file->buffer)
 1247     (clear-stream _test-error-stream)
 1248     (clear-stream $_test-error-buffered-file->buffer)
 1249     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1250     68/push 0/imm32
 1251     68/push 0/imm32
 1252     89/<- %edx 4/r32/esp
 1253     (tailor-exit-descriptor %edx 0x10)
 1254     #
 1255     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1256     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1257     (write _test-input-stream "}\n")
 1258     # convert
 1259     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1260     # registers except esp clobbered at this point
 1261     # restore ed
 1262     89/<- %edx 4/r32/esp
 1263     (flush _test-output-buffered-file)
 1264     (flush _test-error-buffered-file)
 1265 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1271     # check output
 1272     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1273     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1274     # check that stop(1) was called
 1275     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1276     # don't restore from ebp
 1277     81 0/subop/add %esp 8/imm32
 1278     # . epilogue
 1279     5d/pop-to-ebp
 1280     c3/return
 1281 
 1282 test-early-exit-without-return:
 1283     # . prologue
 1284     55/push-ebp
 1285     89/<- %ebp 4/r32/esp
 1286     # setup
 1287     (clear-stream _test-input-stream)
 1288     (clear-stream $_test-input-buffered-file->buffer)
 1289     (clear-stream _test-output-stream)
 1290     (clear-stream $_test-output-buffered-file->buffer)
 1291     (clear-stream _test-error-stream)
 1292     (clear-stream $_test-error-buffered-file->buffer)
 1293     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1294     68/push 0/imm32
 1295     68/push 0/imm32
 1296     89/<- %edx 4/r32/esp
 1297     (tailor-exit-descriptor %edx 0x10)
 1298     #
 1299     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1300     (write _test-input-stream "  break\n")
 1301     (write _test-input-stream "  return 0\n")
 1302     (write _test-input-stream "}\n")
 1303     # convert
 1304     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1305     # registers except esp clobbered at this point
 1306     # restore ed
 1307     89/<- %edx 4/r32/esp
 1308     (flush _test-output-buffered-file)
 1309     (flush _test-error-buffered-file)
 1310 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1316     # check output
 1317     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1318     (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")
 1319     # check that stop(1) was called
 1320     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1321     # don't restore from ebp
 1322     81 0/subop/add %esp 8/imm32
 1323     # . epilogue
 1324     5d/pop-to-ebp
 1325     c3/return
 1326 
 1327 test-return-with-too-few-inouts:
 1328     # . prologue
 1329     55/push-ebp
 1330     89/<- %ebp 4/r32/esp
 1331     # setup
 1332     (clear-stream _test-input-stream)
 1333     (clear-stream $_test-input-buffered-file->buffer)
 1334     (clear-stream _test-output-stream)
 1335     (clear-stream $_test-output-buffered-file->buffer)
 1336     (clear-stream _test-error-stream)
 1337     (clear-stream $_test-error-buffered-file->buffer)
 1338     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1339     68/push 0/imm32
 1340     68/push 0/imm32
 1341     89/<- %edx 4/r32/esp
 1342     (tailor-exit-descriptor %edx 0x10)
 1343     #
 1344     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1345     (write _test-input-stream "  return\n")
 1346     (write _test-input-stream "}\n")
 1347     # convert
 1348     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1349     # registers except esp clobbered at this point
 1350     # restore ed
 1351     89/<- %edx 4/r32/esp
 1352     (flush _test-output-buffered-file)
 1353     (flush _test-error-buffered-file)
 1354 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1360     # check output
 1361     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1362     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1363     # check that stop(1) was called
 1364     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1365     # don't restore from ebp
 1366     81 0/subop/add %esp 8/imm32
 1367     # . epilogue
 1368     5d/pop-to-ebp
 1369     c3/return
 1370 
 1371 test-return-with-too-many-inouts:
 1372     # . prologue
 1373     55/push-ebp
 1374     89/<- %ebp 4/r32/esp
 1375     # setup
 1376     (clear-stream _test-input-stream)
 1377     (clear-stream $_test-input-buffered-file->buffer)
 1378     (clear-stream _test-output-stream)
 1379     (clear-stream $_test-output-buffered-file->buffer)
 1380     (clear-stream _test-error-stream)
 1381     (clear-stream $_test-error-buffered-file->buffer)
 1382     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1383     68/push 0/imm32
 1384     68/push 0/imm32
 1385     89/<- %edx 4/r32/esp
 1386     (tailor-exit-descriptor %edx 0x10)
 1387     #
 1388     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1389     (write _test-input-stream "  return 0, 0\n")
 1390     (write _test-input-stream "}\n")
 1391     # convert
 1392     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1393     # registers except esp clobbered at this point
 1394     # restore ed
 1395     89/<- %edx 4/r32/esp
 1396     (flush _test-output-buffered-file)
 1397     (flush _test-error-buffered-file)
 1398 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1404     # check output
 1405     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1406     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1407     # check that stop(1) was called
 1408     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1409     # don't restore from ebp
 1410     81 0/subop/add %esp 8/imm32
 1411     # . epilogue
 1412     5d/pop-to-ebp
 1413     c3/return
 1414 
 1415 test-return-unavailable-value:
 1416     # . prologue
 1417     55/push-ebp
 1418     89/<- %ebp 4/r32/esp
 1419     # setup
 1420     (clear-stream _test-input-stream)
 1421     (clear-stream $_test-input-buffered-file->buffer)
 1422     (clear-stream _test-output-stream)
 1423     (clear-stream $_test-output-buffered-file->buffer)
 1424     (clear-stream _test-error-stream)
 1425     (clear-stream $_test-error-buffered-file->buffer)
 1426     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1427     68/push 0/imm32
 1428     68/push 0/imm32
 1429     89/<- %edx 4/r32/esp
 1430     (tailor-exit-descriptor %edx 0x10)
 1431     #
 1432     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1433     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1434     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1435     (write _test-input-stream "  return y, x\n")
 1436     (write _test-input-stream "}\n")
 1437     # convert
 1438     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1439     # registers except esp clobbered at this point
 1440     # restore ed
 1441     89/<- %edx 4/r32/esp
 1442     (flush _test-output-buffered-file)
 1443     (flush _test-error-buffered-file)
 1444 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1450     # check output
 1451     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1452     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1453     # check that stop(1) was called
 1454     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1455     # don't restore from ebp
 1456     81 0/subop/add %esp 8/imm32
 1457     # . epilogue
 1458     5d/pop-to-ebp
 1459     c3/return
 1460 
 1461 test-convert-return-with-duplicate-values:
 1462     # . prologue
 1463     55/push-ebp
 1464     89/<- %ebp 4/r32/esp
 1465     # setup
 1466     (clear-stream _test-input-stream)
 1467     (clear-stream $_test-input-buffered-file->buffer)
 1468     (clear-stream _test-output-stream)
 1469     (clear-stream $_test-output-buffered-file->buffer)
 1470     #
 1471     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1472     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1473     (write _test-input-stream "  return x, x\n")
 1474     (write _test-input-stream "}\n")
 1475     # convert
 1476     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1477     (flush _test-output-buffered-file)
 1478 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1484     # check output
 1485     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1486     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1487     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1488     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1489     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1491     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1492     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1493     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1494     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1495     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1496     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1497     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1499     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1500     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1501     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1502     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1503     # . epilogue
 1504     89/<- %esp 5/r32/ebp
 1505     5d/pop-to-ebp
 1506     c3/return
 1507 
 1508 test-convert-return-with-duplicate-values-2:
 1509     # . prologue
 1510     55/push-ebp
 1511     89/<- %ebp 4/r32/esp
 1512     # setup
 1513     (clear-stream _test-input-stream)
 1514     (clear-stream $_test-input-buffered-file->buffer)
 1515     (clear-stream _test-output-stream)
 1516     (clear-stream $_test-output-buffered-file->buffer)
 1517     #
 1518     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1519     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1520     (write _test-input-stream "  return x, x\n")
 1521     (write _test-input-stream "}\n")
 1522     # convert
 1523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1524     (flush _test-output-buffered-file)
 1525 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1531     # check output
 1532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1535     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1538     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1539     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1540     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1541     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1542     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1543     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1544     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1545     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1546     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1547     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1548     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1549     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1550     # . epilogue
 1551     89/<- %esp 5/r32/ebp
 1552     5d/pop-to-ebp
 1553     c3/return
 1554 
 1555 test-convert-function-with-literal-arg:
 1556     # . prologue
 1557     55/push-ebp
 1558     89/<- %ebp 4/r32/esp
 1559     # setup
 1560     (clear-stream _test-input-stream)
 1561     (clear-stream $_test-input-buffered-file->buffer)
 1562     (clear-stream _test-output-stream)
 1563     (clear-stream $_test-output-buffered-file->buffer)
 1564     #
 1565     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 1566     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1567     (write _test-input-stream "  result <- add 1\n")
 1568     (write _test-input-stream "  return result\n")
 1569     (write _test-input-stream "}\n")
 1570     # convert
 1571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1572     (flush _test-output-buffered-file)
 1573 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1579     # check output
 1580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 1581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 1582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 1583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 1584     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 1585     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 1586     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 1587     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 1588     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 1589     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 1590     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 1591     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 1592     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 1593     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 1594     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 1595     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 1596     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 1597     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 1598     # . epilogue
 1599     89/<- %esp 5/r32/ebp
 1600     5d/pop-to-ebp
 1601     c3/return
 1602 
 1603 test-convert-function-with-literal-arg-2:
 1604     # . prologue
 1605     55/push-ebp
 1606     89/<- %ebp 4/r32/esp
 1607     # setup
 1608     (clear-stream _test-input-stream)
 1609     (clear-stream $_test-input-buffered-file->buffer)
 1610     (clear-stream _test-output-stream)
 1611     (clear-stream $_test-output-buffered-file->buffer)
 1612     #
 1613     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 1614     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 1615     (write _test-input-stream "  result <- add 1\n")
 1616     (write _test-input-stream "  return result\n")
 1617     (write _test-input-stream "}\n")
 1618     # convert
 1619     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1620     (flush _test-output-buffered-file)
 1621 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1627     # check output
 1628     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 1629     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 1630     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 1631     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 1632     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 1633     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 1634     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 1635     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 1636     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 1637     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 1638     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 1639     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 1640     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 1641     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 1642     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 1643     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 1644     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 1645     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 1646     # . epilogue
 1647     89/<- %esp 5/r32/ebp
 1648     5d/pop-to-ebp
 1649     c3/return
 1650 
 1651 test-convert-function-call-with-literal-arg:
 1652     # . prologue
 1653     55/push-ebp
 1654     89/<- %ebp 4/r32/esp
 1655     # setup
 1656     (clear-stream _test-input-stream)
 1657     (clear-stream $_test-input-buffered-file->buffer)
 1658     (clear-stream _test-output-stream)
 1659     (clear-stream $_test-output-buffered-file->buffer)
 1660     #
 1661     (write _test-input-stream "fn main -> _/ebx: int {\n")
 1662     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 1663     (write _test-input-stream "  return result\n")
 1664     (write _test-input-stream "}\n")
 1665     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 1666     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1667     (write _test-input-stream "  result <- add b\n")
 1668     (write _test-input-stream "  return result\n")
 1669     (write _test-input-stream "}\n")
 1670     # convert
 1671     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1672     (flush _test-output-buffered-file)
 1673 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1679     # check output
 1680     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 1681     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 1682     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 1683     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 1684     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 1685     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 1686     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 1687     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 1688     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1689     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 1690     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1691     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 1692     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 1693     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 1694     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 1695     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 1696     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 1697     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 1698     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 1699     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 1700     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 1701     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 1702     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 1703     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 1704     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 1705     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 1706     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 1707     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 1708     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 1709     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 1710     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 1711     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 1712     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 1713     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 1714     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 1715     # . epilogue
 1716     89/<- %esp 5/r32/ebp
 1717     5d/pop-to-ebp
 1718     c3/return
 1719 
 1720 test-convert-function-call-with-literal-string-arg:
 1721     # . prologue
 1722     55/push-ebp
 1723     89/<- %ebp 4/r32/esp
 1724     # setup
 1725     (clear-stream _test-input-stream)
 1726     (clear-stream $_test-input-buffered-file->buffer)
 1727     (clear-stream _test-output-stream)
 1728     (clear-stream $_test-output-buffered-file->buffer)
 1729     #
 1730     (write _test-input-stream "fn foo {\n")
 1731     (write _test-input-stream "  string-func \"abc\"\n")
 1732     (write _test-input-stream "}\n")
 1733     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 1734     # convert
 1735     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1736     # no errors
 1737     # not bothering checking output
 1738     # . epilogue
 1739     89/<- %esp 5/r32/ebp
 1740     5d/pop-to-ebp
 1741     c3/return
 1742 
 1743 test-convert-function-call-with-null-addr:
 1744     # . prologue
 1745     55/push-ebp
 1746     89/<- %ebp 4/r32/esp
 1747     # setup
 1748     (clear-stream _test-input-stream)
 1749     (clear-stream $_test-input-buffered-file->buffer)
 1750     (clear-stream _test-output-stream)
 1751     (clear-stream $_test-output-buffered-file->buffer)
 1752     #
 1753     (write _test-input-stream "fn foo {\n")
 1754     (write _test-input-stream "  bar 0\n")
 1755     (write _test-input-stream "}\n")
 1756     (write _test-input-stream "sig bar in: (addr int)\n")
 1757     # convert
 1758     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1759     # no errors
 1760     # not bothering checking output
 1761     # . epilogue
 1762     89/<- %esp 5/r32/ebp
 1763     5d/pop-to-ebp
 1764     c3/return
 1765 
 1766 test-convert-function-call-with-signature:
 1767     # . prologue
 1768     55/push-ebp
 1769     89/<- %ebp 4/r32/esp
 1770     # setup
 1771     (clear-stream _test-input-stream)
 1772     (clear-stream $_test-input-buffered-file->buffer)
 1773     (clear-stream _test-output-stream)
 1774     (clear-stream $_test-output-buffered-file->buffer)
 1775     #
 1776     (write _test-input-stream "fn main -> _/ebx: int {\n")
 1777     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 1778     (write _test-input-stream "  return result\n")
 1779     (write _test-input-stream "}\n")
 1780     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 1781     # convert
 1782     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1783     (flush _test-output-buffered-file)
 1784 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1790     # check output
 1791     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 1792     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 1793     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 1794     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 1795     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 1796     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 1797     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 1798     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 1799     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1800     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 1801     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 1803     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 1804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 1805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 1806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 1807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 1808     # . epilogue
 1809     89/<- %esp 5/r32/ebp
 1810     5d/pop-to-ebp
 1811     c3/return
 1812 
 1813 test-convert-function-with-local-var-in-mem:
 1814     # . prologue
 1815     55/push-ebp
 1816     89/<- %ebp 4/r32/esp
 1817     # setup
 1818     (clear-stream _test-input-stream)
 1819     (clear-stream $_test-input-buffered-file->buffer)
 1820     (clear-stream _test-output-stream)
 1821     (clear-stream $_test-output-buffered-file->buffer)
 1822     #
 1823     (write _test-input-stream "fn foo {\n")
 1824     (write _test-input-stream "  var x: int\n")
 1825     (write _test-input-stream "  increment x\n")
 1826     (write _test-input-stream "}\n")
 1827     # convert
 1828     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1829     (flush _test-output-buffered-file)
 1830 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1836     # check output
 1837     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 1838     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 1839     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 1840     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 1841     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 1842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 1843     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 1844     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 1845     (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")
 1846     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 1847     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 1848     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 1849     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 1850     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 1851     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 1852     # . epilogue
 1853     89/<- %esp 5/r32/ebp
 1854     5d/pop-to-ebp
 1855     c3/return
 1856 
 1857 test-convert-invalid-literal:
 1858     # . prologue
 1859     55/push-ebp
 1860     89/<- %ebp 4/r32/esp
 1861     # setup
 1862     (clear-stream _test-input-stream)
 1863     (clear-stream $_test-input-buffered-file->buffer)
 1864     (clear-stream _test-output-stream)
 1865     (clear-stream $_test-output-buffered-file->buffer)
 1866     (clear-stream _test-error-stream)
 1867     (clear-stream $_test-error-buffered-file->buffer)
 1868     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1869     68/push 0/imm32
 1870     68/push 0/imm32
 1871     89/<- %edx 4/r32/esp
 1872     (tailor-exit-descriptor %edx 0x10)
 1873     #
 1874     (write _test-input-stream "fn foo {\n")
 1875     (write _test-input-stream "  increment 1n\n")
 1876     (write _test-input-stream "}\n")
 1877     # convert
 1878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1879     # registers except esp clobbered at this point
 1880     # restore ed
 1881     89/<- %edx 4/r32/esp
 1882     (flush _test-output-buffered-file)
 1883     (flush _test-error-buffered-file)
 1884 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1890     # check output
 1891     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 1892     (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")
 1893     # check that stop(1) was called
 1894     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 1895     # don't restore from ebp
 1896     81 0/subop/add %esp 8/imm32
 1897     # . epilogue
 1898     5d/pop-to-ebp
 1899     c3/return
 1900 
 1901 test-local-var-in-mem-has-no-initializer:
 1902     # . prologue
 1903     55/push-ebp
 1904     89/<- %ebp 4/r32/esp
 1905     # setup
 1906     (clear-stream _test-input-stream)
 1907     (clear-stream $_test-input-buffered-file->buffer)
 1908     (clear-stream _test-output-stream)
 1909     (clear-stream $_test-output-buffered-file->buffer)
 1910     (clear-stream _test-error-stream)
 1911     (clear-stream $_test-error-buffered-file->buffer)
 1912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1913     68/push 0/imm32
 1914     68/push 0/imm32
 1915     89/<- %edx 4/r32/esp
 1916     (tailor-exit-descriptor %edx 0x10)
 1917     #
 1918     (write _test-input-stream "fn foo {\n")
 1919     (write _test-input-stream "  var x: int <- copy 0\n")
 1920     (write _test-input-stream "  increment x\n")
 1921     (write _test-input-stream "}\n")
 1922     # convert
 1923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1924     # registers except esp clobbered at this point
 1925     # restore ed
 1926     89/<- %edx 4/r32/esp
 1927     (flush _test-output-buffered-file)
 1928     (flush _test-error-buffered-file)
 1929 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1935     # check output
 1936     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 1937     (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")
 1938     # check that stop(1) was called
 1939     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 1940     # don't restore from ebp
 1941     81 0/subop/add %esp 8/imm32
 1942     # . epilogue
 1943     5d/pop-to-ebp
 1944     c3/return
 1945 
 1946 test-convert-function-with-local-var-with-compound-type-in-mem:
 1947     # . prologue
 1948     55/push-ebp
 1949     89/<- %ebp 4/r32/esp
 1950     # setup
 1951     (clear-stream _test-input-stream)
 1952     (clear-stream $_test-input-buffered-file->buffer)
 1953     (clear-stream _test-output-stream)
 1954     (clear-stream $_test-output-buffered-file->buffer)
 1955     #
 1956     (write _test-input-stream "fn foo {\n")
 1957     (write _test-input-stream "  var x: (addr int)\n")
 1958     (write _test-input-stream "  copy-to x, 0\n")
 1959     (write _test-input-stream "}\n")
 1960     # convert
 1961     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1962     (flush _test-output-buffered-file)
 1963 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1969     # check output
 1970     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 1971     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 1972     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 1973     (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")
 1974     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 1975     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 1976     (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")
 1977     (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")
 1978     (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")
 1979     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 1980     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 1981     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 1982     (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")
 1983     (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")
 1984     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 1985     # . epilogue
 1986     89/<- %esp 5/r32/ebp
 1987     5d/pop-to-ebp
 1988     c3/return
 1989 
 1990 test-convert-function-with-local-var-in-reg:
 1991     # . prologue
 1992     55/push-ebp
 1993     89/<- %ebp 4/r32/esp
 1994     # setup
 1995     (clear-stream _test-input-stream)
 1996     (clear-stream $_test-input-buffered-file->buffer)
 1997     (clear-stream _test-output-stream)
 1998     (clear-stream $_test-output-buffered-file->buffer)
 1999     #
 2000     (write _test-input-stream "fn foo {\n")
 2001     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2002     (write _test-input-stream "  x <- increment\n")
 2003     (write _test-input-stream "}\n")
 2004     # convert
 2005     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2006     (flush _test-output-buffered-file)
 2007 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2013     # check output
 2014     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2015     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2016     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2017     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2018     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2019     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2020     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2021     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2022     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2023     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2024     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2025     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2026     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2027     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2028     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2029     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2030     # . epilogue
 2031     89/<- %esp 5/r32/ebp
 2032     5d/pop-to-ebp
 2033     c3/return
 2034 
 2035 test-convert-function-with-allocate:
 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     #
 2045     (write _test-input-stream "fn foo {\n")
 2046     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2047     (write _test-input-stream "  allocate x\n")
 2048     (write _test-input-stream "}\n")
 2049     # convert
 2050     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2051     (flush _test-output-buffered-file)
 2052 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2058     # check output
 2059     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2060     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2061     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2062     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2063     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2064     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2065     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2066     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2067     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2068     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2069     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2070     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2071     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2072     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2073     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2074     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2075     # . epilogue
 2076     89/<- %esp 5/r32/ebp
 2077     5d/pop-to-ebp
 2078     c3/return
 2079 
 2080 test-initializer-in-hex:
 2081     # . prologue
 2082     55/push-ebp
 2083     89/<- %ebp 4/r32/esp
 2084     # setup
 2085     (clear-stream _test-input-stream)
 2086     (clear-stream $_test-input-buffered-file->buffer)
 2087     (clear-stream _test-output-stream)
 2088     (clear-stream $_test-output-buffered-file->buffer)
 2089     (clear-stream _test-error-stream)
 2090     (clear-stream $_test-error-buffered-file->buffer)
 2091     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2092     68/push 0/imm32
 2093     68/push 0/imm32
 2094     89/<- %edx 4/r32/esp
 2095     (tailor-exit-descriptor %edx 0x10)
 2096     #
 2097     (write _test-input-stream "fn foo {\n")
 2098     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2099     (write _test-input-stream "}\n")
 2100     # convert
 2101     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2102     # registers except esp clobbered at this point
 2103     # restore ed
 2104     89/<- %edx 4/r32/esp
 2105     (flush _test-output-buffered-file)
 2106     (flush _test-error-buffered-file)
 2107 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2113     # check output
 2114     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2115     (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")
 2116     # check that stop(1) was called
 2117     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2118     # don't restore from ebp
 2119     81 0/subop/add %esp 8/imm32
 2120     # . epilogue
 2121     5d/pop-to-ebp
 2122     c3/return
 2123 
 2124 test-convert-function-with-second-local-var-in-same-reg:
 2125     # . prologue
 2126     55/push-ebp
 2127     89/<- %ebp 4/r32/esp
 2128     # setup
 2129     (clear-stream _test-input-stream)
 2130     (clear-stream $_test-input-buffered-file->buffer)
 2131     (clear-stream _test-output-stream)
 2132     (clear-stream $_test-output-buffered-file->buffer)
 2133     #
 2134     (write _test-input-stream "fn foo {\n")
 2135     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2136     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2137     (write _test-input-stream "  y <- increment\n")
 2138     (write _test-input-stream "}\n")
 2139     # convert
 2140     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2141     (flush _test-output-buffered-file)
 2142 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2148     # check output
 2149     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2150     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2151     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2152     (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")
 2153     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2154     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2155     (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")
 2156     (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")
 2157     (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")
 2158     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2159     (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")
 2160     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2161     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2162     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2163     (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")
 2164     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2165     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2166     # . epilogue
 2167     89/<- %esp 5/r32/ebp
 2168     5d/pop-to-ebp
 2169     c3/return
 2170 
 2171 test-read-clobbered-reg-var:
 2172     # . prologue
 2173     55/push-ebp
 2174     89/<- %ebp 4/r32/esp
 2175     # setup
 2176     (clear-stream _test-input-stream)
 2177     (clear-stream $_test-input-buffered-file->buffer)
 2178     (clear-stream _test-output-stream)
 2179     (clear-stream $_test-output-buffered-file->buffer)
 2180     (clear-stream _test-error-stream)
 2181     (clear-stream $_test-error-buffered-file->buffer)
 2182     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2183     68/push 0/imm32
 2184     68/push 0/imm32
 2185     89/<- %edx 4/r32/esp
 2186     (tailor-exit-descriptor %edx 0x10)
 2187     #
 2188     (write _test-input-stream "fn foo {\n")
 2189     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2190     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2191     (write _test-input-stream "  x <- increment\n")
 2192     (write _test-input-stream "}\n")
 2193     # convert
 2194     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2195     # registers except esp clobbered at this point
 2196     # restore ed
 2197     89/<- %edx 4/r32/esp
 2198     (flush _test-output-buffered-file)
 2199     (flush _test-error-buffered-file)
 2200 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2206     # check output
 2207     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2208     (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")
 2209     # check that stop(1) was called
 2210     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2211     # don't restore from ebp
 2212     81 0/subop/add %esp 8/imm32
 2213     # . epilogue
 2214     5d/pop-to-ebp
 2215     c3/return
 2216 
 2217 test-overlapping-int-fp-registers:
 2218     # . prologue
 2219     55/push-ebp
 2220     89/<- %ebp 4/r32/esp
 2221     # setup
 2222     (clear-stream _test-input-stream)
 2223     (clear-stream $_test-input-buffered-file->buffer)
 2224     (clear-stream _test-output-stream)
 2225     (clear-stream $_test-output-buffered-file->buffer)
 2226     (clear-stream _test-error-stream)
 2227     (clear-stream $_test-error-buffered-file->buffer)
 2228     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2229     68/push 0/imm32
 2230     68/push 0/imm32
 2231     89/<- %edx 4/r32/esp
 2232     (tailor-exit-descriptor %edx 0x10)
 2233     #
 2234     (write _test-input-stream "fn foo {\n")
 2235     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2236     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2237     (write _test-input-stream "  x <- increment\n")
 2238     (write _test-input-stream "}\n")
 2239     # convert
 2240     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2241     # registers except esp clobbered at this point
 2242     # restore ed
 2243     89/<- %edx 4/r32/esp
 2244     (flush _test-output-buffered-file)
 2245     (flush _test-error-buffered-file)
 2246 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2252     # no errors
 2253     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2254     # don't bother checking the generated code
 2255     # don't restore from ebp
 2256     81 0/subop/add %esp 8/imm32
 2257     # . epilogue
 2258     5d/pop-to-ebp
 2259     c3/return
 2260 
 2261 test-convert-function-call:
 2262     # . prologue
 2263     55/push-ebp
 2264     89/<- %ebp 4/r32/esp
 2265     # setup
 2266     (clear-stream _test-input-stream)
 2267     (clear-stream $_test-input-buffered-file->buffer)
 2268     (clear-stream _test-output-stream)
 2269     (clear-stream $_test-output-buffered-file->buffer)
 2270     #
 2271     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2272     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2273     (write _test-input-stream "  return result\n")
 2274     (write _test-input-stream "}\n")
 2275     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2276     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2277     (write _test-input-stream "  return result\n")
 2278     (write _test-input-stream "}\n")
 2279     # convert
 2280     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2281     (flush _test-output-buffered-file)
 2282 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2288     # check output
 2289     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2290     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2291     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2292     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2293     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2294     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2295     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2296     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2297     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2298     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2299     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2300     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2301     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2302     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2303     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2304     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2305     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2306     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2307     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2308     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2309     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2310     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2312     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2313     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2314     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2315     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2316     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2317     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2318     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2319     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2320     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2321     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2322     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2323     # . epilogue
 2324     89/<- %esp 5/r32/ebp
 2325     5d/pop-to-ebp
 2326     c3/return
 2327 
 2328 test-convert-function-call-with-inout-with-compound-type:
 2329     # . prologue
 2330     55/push-ebp
 2331     89/<- %ebp 4/r32/esp
 2332     # setup
 2333     (clear-stream _test-input-stream)
 2334     (clear-stream $_test-input-buffered-file->buffer)
 2335     (clear-stream _test-output-stream)
 2336     (clear-stream $_test-output-buffered-file->buffer)
 2337     #
 2338     (write _test-input-stream "fn f {\n")
 2339     (write _test-input-stream "  var x: (addr int)\n")
 2340     (write _test-input-stream "  g x\n")
 2341     (write _test-input-stream "}\n")
 2342     (write _test-input-stream "fn g a: (addr int) {\n")
 2343     (write _test-input-stream "}\n")
 2344     # convert
 2345     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2346     (flush _test-output-buffered-file)
 2347 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2353     # check output
 2354     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2355     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2356     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2357     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2358     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2359     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2360     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2361     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2362     (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")
 2363     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2364     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2365     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2366     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2367     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2368     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2369     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2370     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2371     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2372     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2373     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2374     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2375     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2376     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2377     # . epilogue
 2378     89/<- %esp 5/r32/ebp
 2379     5d/pop-to-ebp
 2380     c3/return
 2381 
 2382 test-convert-function-call-with-inout-with-type-parameter:
 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 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 error; types matched
 2419     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 2420     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 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-incorrect-inout-type:
 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: int\n")
 2446     (write _test-input-stream "  g x\n")
 2447     (write _test-input-stream "}\n")
 2448     (write _test-input-stream "fn g a: foo {\n")
 2449     (write _test-input-stream "}\n")
 2450     # convert
 2451     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2452     # registers except esp clobbered at this point
 2453     # restore ed
 2454     89/<- %edx 4/r32/esp
 2455     (flush _test-output-buffered-file)
 2456     (flush _test-error-buffered-file)
 2457 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2463     # check output
 2464     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 2465     (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")
 2466     # check that stop(1) was called
 2467     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 2468     # don't restore from ebp
 2469     81 0/subop/add %esp 8/imm32
 2470     5d/pop-to-ebp
 2471     c3/return
 2472 
 2473 test-convert-function-call-with-inout-with-incorrect-compound-type:
 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 "  var x: (addr int)\n")
 2492     (write _test-input-stream "  g x\n")
 2493     (write _test-input-stream "}\n")
 2494     (write _test-input-stream "fn g a: (addr bool) {\n")
 2495     (write _test-input-stream "}\n")
 2496     # convert
 2497     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2498     # registers except esp clobbered at this point
 2499     # restore ed
 2500     89/<- %edx 4/r32/esp
 2501     (flush _test-output-buffered-file)
 2502     (flush _test-error-buffered-file)
 2503 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2509     # check output
 2510     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 2511     (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")
 2512     # don't restore from ebp
 2513     81 0/subop/add %esp 8/imm32
 2514     # . epilogue
 2515     5d/pop-to-ebp
 2516     c3/return
 2517 
 2518 test-convert-function-call-with-inout-with-multiple-type-parameters:
 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: (addr int)\n")
 2537     (write _test-input-stream "  var y: (addr int)\n")
 2538     (write _test-input-stream "  g x, y\n")
 2539     (write _test-input-stream "}\n")
 2540     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 2541     (write _test-input-stream "}\n")
 2542     # convert
 2543     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2544     # registers except esp clobbered at this point
 2545     # restore ed
 2546     89/<- %edx 4/r32/esp
 2547     (flush _test-output-buffered-file)
 2548     (flush _test-error-buffered-file)
 2549 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2555     # no errors
 2556     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 2557     # don't bother checking the generated code
 2558     # don't restore from ebp
 2559     81 0/subop/add %esp 8/imm32
 2560     # . epilogue
 2561     5d/pop-to-ebp
 2562     c3/return
 2563 
 2564 test-type-parameter-matches-rest-of-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: (addr array int)\n")
 2583     (write _test-input-stream "  g x\n")
 2584     (write _test-input-stream "}\n")
 2585     (write _test-input-stream "fn g a: (addr _) {\n")
 2586     (write _test-input-stream "}\n")
 2587     # convert
 2588     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2589     # registers except esp clobbered at this point
 2590     # restore ed
 2591     89/<- %edx 4/r32/esp
 2592     (flush _test-output-buffered-file)
 2593     (flush _test-error-buffered-file)
 2594 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2600     # no errors
 2601     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 2602     # don't bother checking the generated code
 2603     # don't restore from ebp
 2604     81 0/subop/add %esp 8/imm32
 2605     # . epilogue
 2606     5d/pop-to-ebp
 2607     c3/return
 2608 
 2609 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 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 "  var x: (addr int)\n")
 2628     (write _test-input-stream "  var y: (addr boolean)\n")
 2629     (write _test-input-stream "  g x, y\n")
 2630     (write _test-input-stream "}\n")
 2631     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 2632     (write _test-input-stream "}\n")
 2633     # convert
 2634     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2635     # registers except esp clobbered at this point
 2636     # restore ed
 2637     89/<- %edx 4/r32/esp
 2638     (flush _test-output-buffered-file)
 2639     (flush _test-error-buffered-file)
 2640 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2646     # check output
 2647     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 2648     (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")
 2649     # don't restore from ebp
 2650     81 0/subop/add %esp 8/imm32
 2651     # . epilogue
 2652     5d/pop-to-ebp
 2653     c3/return
 2654 
 2655 test-convert-function-call-with-too-few-inouts:
 2656     # . prologue
 2657     55/push-ebp
 2658     89/<- %ebp 4/r32/esp
 2659     # setup
 2660     (clear-stream _test-input-stream)
 2661     (clear-stream $_test-input-buffered-file->buffer)
 2662     (clear-stream _test-output-stream)
 2663     (clear-stream $_test-output-buffered-file->buffer)
 2664     (clear-stream _test-error-stream)
 2665     (clear-stream $_test-error-buffered-file->buffer)
 2666     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2667     68/push 0/imm32
 2668     68/push 0/imm32
 2669     89/<- %edx 4/r32/esp
 2670     (tailor-exit-descriptor %edx 0x10)
 2671     #
 2672     (write _test-input-stream "fn f {\n")
 2673     (write _test-input-stream "  g\n")
 2674     (write _test-input-stream "}\n")
 2675     (write _test-input-stream "fn g a: int {\n")
 2676     (write _test-input-stream "}\n")
 2677     # convert
 2678     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2679     # registers except esp clobbered at this point
 2680     # restore ed
 2681     89/<- %edx 4/r32/esp
 2682     (flush _test-output-buffered-file)
 2683     (flush _test-error-buffered-file)
 2684 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2690     # check output
 2691     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 2692     (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")
 2693     # check that stop(1) was called
 2694     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 2695     # don't restore from ebp
 2696     81 0/subop/add %esp 8/imm32
 2697     5d/pop-to-ebp
 2698     c3/return
 2699 
 2700 test-convert-function-call-with-too-many-inouts:
 2701     # . prologue
 2702     55/push-ebp
 2703     89/<- %ebp 4/r32/esp
 2704     # setup
 2705     (clear-stream _test-input-stream)
 2706     (clear-stream $_test-input-buffered-file->buffer)
 2707     (clear-stream _test-output-stream)
 2708     (clear-stream $_test-output-buffered-file->buffer)
 2709     (clear-stream _test-error-stream)
 2710     (clear-stream $_test-error-buffered-file->buffer)
 2711     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2712     68/push 0/imm32
 2713     68/push 0/imm32
 2714     89/<- %edx 4/r32/esp
 2715     (tailor-exit-descriptor %edx 0x10)
 2716     #
 2717     (write _test-input-stream "fn f {\n")
 2718     (write _test-input-stream "  var x: int\n")
 2719     (write _test-input-stream "  g x\n")
 2720     (write _test-input-stream "}\n")
 2721     (write _test-input-stream "fn g {\n")
 2722     (write _test-input-stream "}\n")
 2723     # convert
 2724     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2725     # registers except esp clobbered at this point
 2726     # restore ed
 2727     89/<- %edx 4/r32/esp
 2728     (flush _test-output-buffered-file)
 2729     (flush _test-error-buffered-file)
 2730 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2736     # check output
 2737     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 2738     (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")
 2739     # check that stop(1) was called
 2740     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 2741     # don't restore from ebp
 2742     81 0/subop/add %esp 8/imm32
 2743     5d/pop-to-ebp
 2744     c3/return
 2745 
 2746 test-convert-function-call-with-incorrect-output-type:
 2747     # . prologue
 2748     55/push-ebp
 2749     89/<- %ebp 4/r32/esp
 2750     # setup
 2751     (clear-stream _test-input-stream)
 2752     (clear-stream $_test-input-buffered-file->buffer)
 2753     (clear-stream _test-output-stream)
 2754     (clear-stream $_test-output-buffered-file->buffer)
 2755     (clear-stream _test-error-stream)
 2756     (clear-stream $_test-error-buffered-file->buffer)
 2757     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2758     68/push 0/imm32
 2759     68/push 0/imm32
 2760     89/<- %edx 4/r32/esp
 2761     (tailor-exit-descriptor %edx 0x10)
 2762     #
 2763     (write _test-input-stream "fn f {\n")
 2764     (write _test-input-stream "  var x/eax: int <- g\n")
 2765     (write _test-input-stream "}\n")
 2766     (write _test-input-stream "fn g -> _/eax: foo {\n")
 2767     (write _test-input-stream "}\n")
 2768     # convert
 2769     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2770     # registers except esp clobbered at this point
 2771     # restore ed
 2772     89/<- %edx 4/r32/esp
 2773     (flush _test-output-buffered-file)
 2774     (flush _test-error-buffered-file)
 2775 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2781     # check output
 2782     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 2783     (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")
 2784     # check that stop(1) was called
 2785     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 2786     # don't restore from ebp
 2787     81 0/subop/add %esp 8/imm32
 2788     5d/pop-to-ebp
 2789     c3/return
 2790 
 2791 test-convert-function-call-with-too-few-outputs:
 2792     # . prologue
 2793     55/push-ebp
 2794     89/<- %ebp 4/r32/esp
 2795     # setup
 2796     (clear-stream _test-input-stream)
 2797     (clear-stream $_test-input-buffered-file->buffer)
 2798     (clear-stream _test-output-stream)
 2799     (clear-stream $_test-output-buffered-file->buffer)
 2800     (clear-stream _test-error-stream)
 2801     (clear-stream $_test-error-buffered-file->buffer)
 2802     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2803     68/push 0/imm32
 2804     68/push 0/imm32
 2805     89/<- %edx 4/r32/esp
 2806     (tailor-exit-descriptor %edx 0x10)
 2807     #
 2808     (write _test-input-stream "fn f {\n")
 2809     (write _test-input-stream "  g\n")
 2810     (write _test-input-stream "}\n")
 2811     (write _test-input-stream "fn g -> _/eax: int {\n")
 2812     (write _test-input-stream "}\n")
 2813     # convert
 2814     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2815     # registers except esp clobbered at this point
 2816     # restore ed
 2817     89/<- %edx 4/r32/esp
 2818     (flush _test-output-buffered-file)
 2819     (flush _test-error-buffered-file)
 2820 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2826     # check output
 2827     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 2828     (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")
 2829     # check that stop(1) was called
 2830     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 2831     # don't restore from ebp
 2832     81 0/subop/add %esp 8/imm32
 2833     5d/pop-to-ebp
 2834     c3/return
 2835 
 2836 test-convert-function-call-with-too-many-outputs:
 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     (clear-stream _test-error-stream)
 2846     (clear-stream $_test-error-buffered-file->buffer)
 2847     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2848     68/push 0/imm32
 2849     68/push 0/imm32
 2850     89/<- %edx 4/r32/esp
 2851     (tailor-exit-descriptor %edx 0x10)
 2852     #
 2853     (write _test-input-stream "fn f {\n")
 2854     (write _test-input-stream "  var x/eax: int <- g\n")
 2855     (write _test-input-stream "}\n")
 2856     (write _test-input-stream "fn g {\n")
 2857     (write _test-input-stream "}\n")
 2858     # convert
 2859     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2860     # registers except esp clobbered at this point
 2861     # restore ed
 2862     89/<- %edx 4/r32/esp
 2863     (flush _test-output-buffered-file)
 2864     (flush _test-error-buffered-file)
 2865 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2871     # check output
 2872     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 2873     (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")
 2874     # check that stop(1) was called
 2875     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 2876     # don't restore from ebp
 2877     81 0/subop/add %esp 8/imm32
 2878     5d/pop-to-ebp
 2879     c3/return
 2880 
 2881 test-convert-function-call-with-missing-output-register:
 2882     # . prologue
 2883     55/push-ebp
 2884     89/<- %ebp 4/r32/esp
 2885     # setup
 2886     (clear-stream _test-input-stream)
 2887     (clear-stream $_test-input-buffered-file->buffer)
 2888     (clear-stream _test-output-stream)
 2889     (clear-stream $_test-output-buffered-file->buffer)
 2890     (clear-stream _test-error-stream)
 2891     (clear-stream $_test-error-buffered-file->buffer)
 2892     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2893     68/push 0/imm32
 2894     68/push 0/imm32
 2895     89/<- %edx 4/r32/esp
 2896     (tailor-exit-descriptor %edx 0x10)
 2897     #
 2898     (write _test-input-stream "fn f {\n")
 2899     (write _test-input-stream "  var x: int\n")
 2900     (write _test-input-stream "  x <- g\n")
 2901     (write _test-input-stream "}\n")
 2902     (write _test-input-stream "fn g -> _/eax: int {\n")
 2903     (write _test-input-stream "}\n")
 2904     # convert
 2905     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2906     # registers except esp clobbered at this point
 2907     # restore ed
 2908     89/<- %edx 4/r32/esp
 2909     (flush _test-output-buffered-file)
 2910     (flush _test-error-buffered-file)
 2911 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2917     # check output
 2918     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 2919     (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")
 2920     # check that stop(1) was called
 2921     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 2922     # don't restore from ebp
 2923     81 0/subop/add %esp 8/imm32
 2924     5d/pop-to-ebp
 2925     c3/return
 2926 
 2927 test-convert-function-call-with-incorrect-output-register:
 2928     # . prologue
 2929     55/push-ebp
 2930     89/<- %ebp 4/r32/esp
 2931     # setup
 2932     (clear-stream _test-input-stream)
 2933     (clear-stream $_test-input-buffered-file->buffer)
 2934     (clear-stream _test-output-stream)
 2935     (clear-stream $_test-output-buffered-file->buffer)
 2936     (clear-stream _test-error-stream)
 2937     (clear-stream $_test-error-buffered-file->buffer)
 2938     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2939     68/push 0/imm32
 2940     68/push 0/imm32
 2941     89/<- %edx 4/r32/esp
 2942     (tailor-exit-descriptor %edx 0x10)
 2943     #
 2944     (write _test-input-stream "fn f {\n")
 2945     (write _test-input-stream "  var x/ecx: int <- g\n")
 2946     (write _test-input-stream "}\n")
 2947     (write _test-input-stream "fn g -> _/eax: int {\n")
 2948     (write _test-input-stream "}\n")
 2949     # convert
 2950     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2951     # registers except esp clobbered at this point
 2952     # restore ed
 2953     89/<- %edx 4/r32/esp
 2954     (flush _test-output-buffered-file)
 2955     (flush _test-error-buffered-file)
 2956 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2962     # check output
 2963     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 2964     (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")
 2965     # check that stop(1) was called
 2966     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 2967     # don't restore from ebp
 2968     81 0/subop/add %esp 8/imm32
 2969     5d/pop-to-ebp
 2970     c3/return
 2971 
 2972 test-convert-function-with-local-var-dereferenced:
 2973     # . prologue
 2974     55/push-ebp
 2975     89/<- %ebp 4/r32/esp
 2976     # setup
 2977     (clear-stream _test-input-stream)
 2978     (clear-stream $_test-input-buffered-file->buffer)
 2979     (clear-stream _test-output-stream)
 2980     (clear-stream $_test-output-buffered-file->buffer)
 2981     #
 2982     (write _test-input-stream "fn foo {\n")
 2983     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2984     (write _test-input-stream "  increment *x\n")
 2985     (write _test-input-stream "}\n")
 2986     # convert
 2987     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2988     (flush _test-output-buffered-file)
 2989 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2995     # check output
 2996     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 2997     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 2998     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 2999     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3000     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3001     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3002     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3003     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3004     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3005     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3006     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3007     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3009     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3011     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3012     # . epilogue
 3013     89/<- %esp 5/r32/ebp
 3014     5d/pop-to-ebp
 3015     c3/return
 3016 
 3017 test-dereference-of-var-on-stack:
 3018     # . prologue
 3019     55/push-ebp
 3020     89/<- %ebp 4/r32/esp
 3021     # setup
 3022     (clear-stream _test-input-stream)
 3023     (clear-stream $_test-input-buffered-file->buffer)
 3024     (clear-stream _test-output-stream)
 3025     (clear-stream $_test-output-buffered-file->buffer)
 3026     (clear-stream _test-error-stream)
 3027     (clear-stream $_test-error-buffered-file->buffer)
 3028     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3029     68/push 0/imm32
 3030     68/push 0/imm32
 3031     89/<- %edx 4/r32/esp
 3032     (tailor-exit-descriptor %edx 0x10)
 3033     #
 3034     (write _test-input-stream "fn foo {\n")
 3035     (write _test-input-stream "  var x: (addr int)\n")
 3036     (write _test-input-stream "  increment *x\n")
 3037     (write _test-input-stream "}\n")
 3038     # convert
 3039     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3040     # registers except esp clobbered at this point
 3041     # restore ed
 3042     89/<- %edx 4/r32/esp
 3043     (flush _test-output-buffered-file)
 3044     (flush _test-error-buffered-file)
 3045 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3051     # check output
 3052     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3053     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
 3054     # check that stop(1) was called
 3055     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3056     # don't restore from ebp
 3057     81 0/subop/add %esp 8/imm32
 3058     # . epilogue
 3059     5d/pop-to-ebp
 3060     c3/return
 3061 
 3062 # variables of type 'byte' are not allowed on the stack
 3063 test-convert-function-with-byte-operations:
 3064     # . prologue
 3065     55/push-ebp
 3066     89/<- %ebp 4/r32/esp
 3067     # setup
 3068     (clear-stream _test-input-stream)
 3069     (clear-stream $_test-input-buffered-file->buffer)
 3070     (clear-stream _test-output-stream)
 3071     (clear-stream $_test-output-buffered-file->buffer)
 3072     #
 3073     (write _test-input-stream "fn foo {\n")
 3074     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3075     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3076     (write _test-input-stream "  y <- copy-byte x\n")
 3077     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3078     (write _test-input-stream "  y <- copy-byte *z\n")
 3079     (write _test-input-stream "  copy-byte-to *z, x\n")
 3080     (write _test-input-stream "}\n")
 3081     # convert
 3082     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3083     (flush _test-output-buffered-file)
 3084 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3090     # check output
 3091     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3092     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3093     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3094     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3095     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3096     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3097     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3098     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3099     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3100     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3101     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3102     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 3103     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 3104     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 3105     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 3106     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 3107     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 3108     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 3109     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 3110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 3111     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 3112     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 3113     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 3114     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 3115     # . epilogue
 3116     89/<- %esp 5/r32/ebp
 3117     5d/pop-to-ebp
 3118     c3/return
 3119 
 3120 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3121 test-copy-byte-var-from-fn-arg:
 3122     # . prologue
 3123     55/push-ebp
 3124     89/<- %ebp 4/r32/esp
 3125     # setup
 3126     (clear-stream _test-input-stream)
 3127     (clear-stream $_test-input-buffered-file->buffer)
 3128     (clear-stream _test-output-stream)
 3129     (clear-stream $_test-output-buffered-file->buffer)
 3130     #
 3131     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3132     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3133     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3134     (write _test-input-stream "}\n")
 3135     # convert
 3136     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3137     (flush _test-output-buffered-file)
 3138 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3144     # check output
 3145     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3146     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3147     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3148     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3149     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3151     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3152     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3153     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3154     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3155     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3156     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3157     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3158     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3159     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3160     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3161     # . epilogue
 3162     89/<- %esp 5/r32/ebp
 3163     5d/pop-to-ebp
 3164     c3/return
 3165 
 3166 test-convert-compare-register-with-literal:
 3167     # . prologue
 3168     55/push-ebp
 3169     89/<- %ebp 4/r32/esp
 3170     # setup
 3171     (clear-stream _test-input-stream)
 3172     (clear-stream $_test-input-buffered-file->buffer)
 3173     (clear-stream _test-output-stream)
 3174     (clear-stream $_test-output-buffered-file->buffer)
 3175     #
 3176     (write _test-input-stream "fn foo {\n")
 3177     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3178     (write _test-input-stream "  compare x, 0\n")
 3179     (write _test-input-stream "}\n")
 3180     # convert
 3181     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3182     (flush _test-output-buffered-file)
 3183 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3189     # check output
 3190     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 3191     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 3192     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 3193     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 3194     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 3195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 3196     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3197     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 3198     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 3199     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3200     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 3201     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 3202     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 3203     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 3204     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 3205     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 3206     # . epilogue
 3207     89/<- %esp 5/r32/ebp
 3208     5d/pop-to-ebp
 3209     c3/return
 3210 
 3211 test-unknown-variable:
 3212     # . prologue
 3213     55/push-ebp
 3214     89/<- %ebp 4/r32/esp
 3215     # setup
 3216     (clear-stream _test-input-stream)
 3217     (clear-stream $_test-input-buffered-file->buffer)
 3218     (clear-stream _test-output-stream)
 3219     (clear-stream $_test-output-buffered-file->buffer)
 3220     (clear-stream _test-error-stream)
 3221     (clear-stream $_test-error-buffered-file->buffer)
 3222     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3223     68/push 0/imm32
 3224     68/push 0/imm32
 3225     89/<- %edx 4/r32/esp
 3226     (tailor-exit-descriptor %edx 0x10)
 3227     #
 3228     (write _test-input-stream "fn foo {\n")
 3229     (write _test-input-stream "  compare x, 0\n")
 3230     (write _test-input-stream "}\n")
 3231     # convert
 3232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3233     # registers except esp clobbered at this point
 3234     # restore ed
 3235     89/<- %edx 4/r32/esp
 3236     (flush _test-output-buffered-file)
 3237     (flush _test-error-buffered-file)
 3238 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3244     # check output
 3245     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3246     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3247     # check that stop(1) was called
 3248     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3249     # don't restore from ebp
 3250     81 0/subop/add %esp 8/imm32
 3251     # . epilogue
 3252     5d/pop-to-ebp
 3253     c3/return
 3254 
 3255 test-convert-function-with-local-var-in-block:
 3256     # . prologue
 3257     55/push-ebp
 3258     89/<- %ebp 4/r32/esp
 3259     # setup
 3260     (clear-stream _test-input-stream)
 3261     (clear-stream $_test-input-buffered-file->buffer)
 3262     (clear-stream _test-output-stream)
 3263     (clear-stream $_test-output-buffered-file->buffer)
 3264     #
 3265     (write _test-input-stream "fn foo {\n")
 3266     (write _test-input-stream "  {\n")
 3267     (write _test-input-stream "    var x: int\n")
 3268     (write _test-input-stream "    increment x\n")
 3269     (write _test-input-stream "  }\n")
 3270     (write _test-input-stream "}\n")
 3271     # convert
 3272     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3273     (flush _test-output-buffered-file)
 3274 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3280     # check output
 3281     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 3282     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 3283     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 3284     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 3285     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 3286     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 3287     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 3288     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 3289     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 3290     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 3291     (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")
 3292     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 3293     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 3294     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 3295     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 3296     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 3297     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 3298     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 3299     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 3300     # . epilogue
 3301     89/<- %esp 5/r32/ebp
 3302     5d/pop-to-ebp
 3303     c3/return
 3304 
 3305 test-convert-function-with-local-var-in-mem-after-block:
 3306     # . prologue
 3307     55/push-ebp
 3308     89/<- %ebp 4/r32/esp
 3309     # setup
 3310     (clear-stream _test-input-stream)
 3311     (clear-stream $_test-input-buffered-file->buffer)
 3312     (clear-stream _test-output-stream)
 3313     (clear-stream $_test-output-buffered-file->buffer)
 3314     #
 3315     (write _test-input-stream "fn foo {\n")
 3316     (write _test-input-stream "  {\n")
 3317     (write _test-input-stream "    var y: int\n")
 3318     (write _test-input-stream "  }\n")
 3319     (write _test-input-stream "  var x: int\n")
 3320     (write _test-input-stream "  increment x\n")
 3321     (write _test-input-stream "}\n")
 3322     # convert
 3323     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3324     (flush _test-output-buffered-file)
 3325 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3331     # check output
 3332     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 3333     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 3334     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 3335     (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")
 3336     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 3337     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 3338     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 3339     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 3340     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 3341     (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")
 3342     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 3343     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 3344     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 3345     (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")
 3346     (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")
 3347     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 3348     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 3349     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 3350     (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")
 3351     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 3352     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 3353     # . epilogue
 3354     89/<- %esp 5/r32/ebp
 3355     5d/pop-to-ebp
 3356     c3/return
 3357 
 3358 test-convert-function-with-local-var-in-named-block:
 3359     # . prologue
 3360     55/push-ebp
 3361     89/<- %ebp 4/r32/esp
 3362     # setup
 3363     (clear-stream _test-input-stream)
 3364     (clear-stream $_test-input-buffered-file->buffer)
 3365     (clear-stream _test-output-stream)
 3366     (clear-stream $_test-output-buffered-file->buffer)
 3367     #
 3368     (write _test-input-stream "fn foo {\n")
 3369     (write _test-input-stream "  $bar: {\n")
 3370     (write _test-input-stream "    var x: int\n")
 3371     (write _test-input-stream "    increment x\n")
 3372     (write _test-input-stream "  }\n")
 3373     (write _test-input-stream "}\n")
 3374     # convert
 3375     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3376     (flush _test-output-buffered-file)
 3377 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3383     # check output
 3384     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 3385     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 3386     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 3387     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 3388     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 3389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 3390     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 3391     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 3392     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 3393     (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")
 3394     (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")
 3395     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 3396     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 3397     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 3398     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 3399     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 3400     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 3401     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 3402     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 3403     # . epilogue
 3404     89/<- %esp 5/r32/ebp
 3405     5d/pop-to-ebp
 3406     c3/return
 3407 
 3408 test-unknown-variable-in-named-block:
 3409     # . prologue
 3410     55/push-ebp
 3411     89/<- %ebp 4/r32/esp
 3412     # setup
 3413     (clear-stream _test-input-stream)
 3414     (clear-stream $_test-input-buffered-file->buffer)
 3415     (clear-stream _test-output-stream)
 3416     (clear-stream $_test-output-buffered-file->buffer)
 3417     (clear-stream _test-error-stream)
 3418     (clear-stream $_test-error-buffered-file->buffer)
 3419     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3420     68/push 0/imm32
 3421     68/push 0/imm32
 3422     89/<- %edx 4/r32/esp
 3423     (tailor-exit-descriptor %edx 0x10)
 3424     #
 3425     (write _test-input-stream "fn foo {\n")
 3426     (write _test-input-stream "  $a: {\n")
 3427     (write _test-input-stream "    compare x, 0\n")
 3428     (write _test-input-stream "  }\n")
 3429     (write _test-input-stream "}\n")
 3430     # convert
 3431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3432     # registers except esp clobbered at this point
 3433     # restore ed
 3434     89/<- %edx 4/r32/esp
 3435     (flush _test-output-buffered-file)
 3436     (flush _test-error-buffered-file)
 3437 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3443     # check output
 3444     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 3445     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 3446     # check that stop(1) was called
 3447     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 3448     # don't restore from ebp
 3449     81 0/subop/add %esp 8/imm32
 3450     # . epilogue
 3451     5d/pop-to-ebp
 3452     c3/return
 3453 
 3454 test-always-shadow-outermost-reg-vars-in-function:
 3455     # . prologue
 3456     55/push-ebp
 3457     89/<- %ebp 4/r32/esp
 3458     # setup
 3459     (clear-stream _test-input-stream)
 3460     (clear-stream $_test-input-buffered-file->buffer)
 3461     (clear-stream _test-output-stream)
 3462     (clear-stream $_test-output-buffered-file->buffer)
 3463     #
 3464     (write _test-input-stream "fn foo {\n")
 3465     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3466     (write _test-input-stream "}\n")
 3467     # convert
 3468     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3469     (flush _test-output-buffered-file)
 3470 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3476     # check output
 3477     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 3478     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 3479     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 3480     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 3481     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 3482     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 3483     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3484     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 3485     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3486     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 3487     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 3488     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 3489     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 3490     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 3491     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 3492     # . epilogue
 3493     89/<- %esp 5/r32/ebp
 3494     5d/pop-to-ebp
 3495     c3/return
 3496 
 3497 test-shadow-local:
 3498     # . prologue
 3499     55/push-ebp
 3500     89/<- %ebp 4/r32/esp
 3501     # setup
 3502     (clear-stream _test-input-stream)
 3503     (clear-stream $_test-input-buffered-file->buffer)
 3504     (clear-stream _test-output-stream)
 3505     (clear-stream $_test-output-buffered-file->buffer)
 3506     #
 3507     (write _test-input-stream "fn foo {\n")
 3508     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3509     (write _test-input-stream "  {\n")
 3510     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 3511     (write _test-input-stream "  }\n")
 3512     (write _test-input-stream "  x <- increment\n")
 3513     (write _test-input-stream "}\n")
 3514     # convert
 3515     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3516     (flush _test-output-buffered-file)
 3517 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3523     # check output
 3524     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 3525     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 3526     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 3527     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 3528     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 3529     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 3530     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 3531     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 3532     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 3533     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 3534     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 3535     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 3536     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 3537     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 3538     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 3539     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 3540     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 3541     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 3542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 3543     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 3544     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 3545     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 3546     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 3547     # . epilogue
 3548     89/<- %esp 5/r32/ebp
 3549     5d/pop-to-ebp
 3550     c3/return
 3551 
 3552 test-shadow-name:
 3553     # . prologue
 3554     55/push-ebp
 3555     89/<- %ebp 4/r32/esp
 3556     # setup
 3557     (clear-stream _test-input-stream)
 3558     (clear-stream $_test-input-buffered-file->buffer)
 3559     (clear-stream _test-output-stream)
 3560     (clear-stream $_test-output-buffered-file->buffer)
 3561     #
 3562     (write _test-input-stream "fn foo {\n")
 3563     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3564     (write _test-input-stream "  {\n")
 3565     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 3566     (write _test-input-stream "  }\n")
 3567     (write _test-input-stream "  x <- increment\n")
 3568     (write _test-input-stream "}\n")
 3569     # convert
 3570     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3571     (flush _test-output-buffered-file)
 3572 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3578     # check output
 3579     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 3580     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 3581     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 3582     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 3583     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 3584     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 3585     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 3586     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 3587     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 3588     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 3589     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 3590     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 3591     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 3592     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 3593     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 3594     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 3595     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 3596     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 3597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 3598     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 3599     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 3600     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 3601     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 3602     # . epilogue
 3603     89/<- %esp 5/r32/ebp
 3604     5d/pop-to-ebp
 3605     c3/return
 3606 
 3607 test-shadow-name-2:
 3608     # . prologue
 3609     55/push-ebp
 3610     89/<- %ebp 4/r32/esp
 3611     # setup
 3612     (clear-stream _test-input-stream)
 3613     (clear-stream $_test-input-buffered-file->buffer)
 3614     (clear-stream _test-output-stream)
 3615     (clear-stream $_test-output-buffered-file->buffer)
 3616     #
 3617     (write _test-input-stream "fn foo {\n")
 3618     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3619     (write _test-input-stream "  {\n")
 3620     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 3621     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 3622     (write _test-input-stream "  }\n")
 3623     (write _test-input-stream "  x <- increment\n")
 3624     (write _test-input-stream "}\n")
 3625     # convert
 3626     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3627     (flush _test-output-buffered-file)
 3628 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3634     # check output
 3635     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 3636     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 3637     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 3638     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 3639     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 3640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 3641     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 3642     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 3643     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 3644     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 3645     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 3646     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 3647     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 3648     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 3649     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 3650     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 3651     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 3652     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 3653     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 3654     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 3655     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 3656     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 3657     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 3658     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 3659     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 3660     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 3661     # . epilogue
 3662     89/<- %esp 5/r32/ebp
 3663     5d/pop-to-ebp
 3664     c3/return
 3665 
 3666 test-do-not-spill-same-register-in-block:
 3667     # . prologue
 3668     55/push-ebp
 3669     89/<- %ebp 4/r32/esp
 3670     # setup
 3671     (clear-stream _test-input-stream)
 3672     (clear-stream $_test-input-buffered-file->buffer)
 3673     (clear-stream _test-output-stream)
 3674     (clear-stream $_test-output-buffered-file->buffer)
 3675     #
 3676     (write _test-input-stream "fn foo {\n")
 3677     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 3678     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 3679     (write _test-input-stream "  y <- increment\n")
 3680     (write _test-input-stream "}\n")
 3681     # convert
 3682     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3683     (flush _test-output-buffered-file)
 3684 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3690     # check output
 3691     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 3692     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 3693     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 3694     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 3695     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 3696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 3697     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 3698     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 3699     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 3700     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 3701     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 3702     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 3703     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 3704     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 3705     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 3706     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 3707     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 3708     # . epilogue
 3709     89/<- %esp 5/r32/ebp
 3710     5d/pop-to-ebp
 3711     c3/return
 3712 
 3713 test-spill-different-register-in-block:
 3714     # . prologue
 3715     55/push-ebp
 3716     89/<- %ebp 4/r32/esp
 3717     # setup
 3718     (clear-stream _test-input-stream)
 3719     (clear-stream $_test-input-buffered-file->buffer)
 3720     (clear-stream _test-output-stream)
 3721     (clear-stream $_test-output-buffered-file->buffer)
 3722     #
 3723     (write _test-input-stream "fn foo {\n")
 3724     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 3725     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 3726     (write _test-input-stream "  y <- increment\n")
 3727     (write _test-input-stream "}\n")
 3728     # convert
 3729     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3730     (flush _test-output-buffered-file)
 3731 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3737     # check output
 3738     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 3739     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 3740     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 3741     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 3742     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 3743     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 3744     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 3745     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 3746     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 3747     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 3748     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 3749     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 3750     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 3751     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 3752     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 3753     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 3754     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 3755     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 3756     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 3757     # . epilogue
 3758     89/<- %esp 5/r32/ebp
 3759     5d/pop-to-ebp
 3760     c3/return
 3761 
 3762 test-convert-function-with-branches-in-block:
 3763     # . prologue
 3764     55/push-ebp
 3765     89/<- %ebp 4/r32/esp
 3766     # setup
 3767     (clear-stream _test-input-stream)
 3768     (clear-stream $_test-input-buffered-file->buffer)
 3769     (clear-stream _test-output-stream)
 3770     (clear-stream $_test-output-buffered-file->buffer)
 3771     #
 3772     (write _test-input-stream "fn foo x: int {\n")
 3773     (write _test-input-stream "  {\n")
 3774     (write _test-input-stream "    break-if->=\n")
 3775     (write _test-input-stream "    loop-if-addr<\n")
 3776     (write _test-input-stream "    increment x\n")
 3777     (write _test-input-stream "    loop\n")
 3778     (write _test-input-stream "  }\n")
 3779     (write _test-input-stream "}\n")
 3780     # convert
 3781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3782     (flush _test-output-buffered-file)
 3783 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3789     # check output
 3790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3796     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3797     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3798     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3799     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3800     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3801     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3802     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3803     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3804     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3805     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3806     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3807     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3808     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3809     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3810     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3811     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3812     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3813     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3814     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3815     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3816     # . epilogue
 3817     89/<- %esp 5/r32/ebp
 3818     5d/pop-to-ebp
 3819     c3/return
 3820 
 3821 test-convert-function-with-branches-in-block-2:
 3822     # . prologue
 3823     55/push-ebp
 3824     89/<- %ebp 4/r32/esp
 3825     # setup
 3826     (clear-stream _test-input-stream)
 3827     (clear-stream $_test-input-buffered-file->buffer)
 3828     (clear-stream _test-output-stream)
 3829     (clear-stream $_test-output-buffered-file->buffer)
 3830     #
 3831     (write _test-input-stream "fn foo x: int {\n")
 3832     (write _test-input-stream "  {\n")
 3833     (write _test-input-stream "    break-if->=\n")
 3834     (write _test-input-stream "    loop-if-float<\n")
 3835     (write _test-input-stream "    increment x\n")
 3836     (write _test-input-stream "    loop\n")
 3837     (write _test-input-stream "  }\n")
 3838     (write _test-input-stream "}\n")
 3839     # convert
 3840     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3841     (flush _test-output-buffered-file)
 3842 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3848     # check output
 3849     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3850     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3851     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3852     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3853     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3854     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3855     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3856     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3857     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3858     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3859     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3860     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3861     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3862     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3863     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3864     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3865     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3866     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3867     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3868     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3869     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3870     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3871     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3872     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3873     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3874     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3875     # . epilogue
 3876     89/<- %esp 5/r32/ebp
 3877     5d/pop-to-ebp
 3878     c3/return
 3879 
 3880 test-convert-function-with-branches-in-named-block:
 3881     # . prologue
 3882     55/push-ebp
 3883     89/<- %ebp 4/r32/esp
 3884     # setup
 3885     (clear-stream _test-input-stream)
 3886     (clear-stream $_test-input-buffered-file->buffer)
 3887     (clear-stream _test-output-stream)
 3888     (clear-stream $_test-output-buffered-file->buffer)
 3889     #
 3890     (write _test-input-stream "fn foo x: int {\n")
 3891     (write _test-input-stream "  $bar: {\n")
 3892     (write _test-input-stream "    break-if->= $bar\n")
 3893     (write _test-input-stream "    loop-if-addr< $bar\n")
 3894     (write _test-input-stream "    increment x\n")
 3895     (write _test-input-stream "    loop\n")
 3896     (write _test-input-stream "  }\n")
 3897     (write _test-input-stream "}\n")
 3898     # convert
 3899     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3900     (flush _test-output-buffered-file)
 3901 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3907     # check output
 3908     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 3909     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 3910     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 3911     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 3912     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 3913     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 3914     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 3915     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 3916     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 3917     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 3918     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 3919     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 3920     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 3921     (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")
 3922     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 3923     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 3924     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 3925     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 3926     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 3927     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 3928     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 3929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 3930     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 3931     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 3932     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 3933     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 3934     # . epilogue
 3935     89/<- %esp 5/r32/ebp
 3936     5d/pop-to-ebp
 3937     c3/return
 3938 
 3939 test-convert-function-with-var-in-nested-block:
 3940     # . prologue
 3941     55/push-ebp
 3942     89/<- %ebp 4/r32/esp
 3943     # setup
 3944     (clear-stream _test-input-stream)
 3945     (clear-stream $_test-input-buffered-file->buffer)
 3946     (clear-stream _test-output-stream)
 3947     (clear-stream $_test-output-buffered-file->buffer)
 3948     #
 3949     (write _test-input-stream "fn foo x: int {\n")
 3950     (write _test-input-stream "  {\n")
 3951     (write _test-input-stream "    {\n")
 3952     (write _test-input-stream "      var x: int\n")
 3953     (write _test-input-stream "      increment x\n")
 3954     (write _test-input-stream "    }\n")
 3955     (write _test-input-stream "  }\n")
 3956     (write _test-input-stream "}\n")
 3957     # convert
 3958     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3959     (flush _test-output-buffered-file)
 3960 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3966     # check output
 3967     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 3968     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 3969     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 3970     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 3971     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 3972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 3973     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 3974     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 3975     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 3976     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 3977     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 3978     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 3979     (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")
 3980     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 3981     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 3982     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 3983     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 3984     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 3985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 3986     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 3987     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 3988     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 3989     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 3990     # . epilogue
 3991     89/<- %esp 5/r32/ebp
 3992     5d/pop-to-ebp
 3993     c3/return
 3994 
 3995 test-convert-function-with-multiple-vars-in-nested-blocks:
 3996     # . prologue
 3997     55/push-ebp
 3998     89/<- %ebp 4/r32/esp
 3999     # setup
 4000     (clear-stream _test-input-stream)
 4001     (clear-stream $_test-input-buffered-file->buffer)
 4002     (clear-stream _test-output-stream)
 4003     (clear-stream $_test-output-buffered-file->buffer)
 4004     #
 4005     (write _test-input-stream "fn foo x: int {\n")
 4006     (write _test-input-stream "  {\n")
 4007     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4008     (write _test-input-stream "    {\n")
 4009     (write _test-input-stream "      var y: int\n")
 4010     (write _test-input-stream "      x <- add y\n")
 4011     (write _test-input-stream "    }\n")
 4012     (write _test-input-stream "  }\n")
 4013     (write _test-input-stream "}\n")
 4014     # convert
 4015     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4016     (flush _test-output-buffered-file)
 4017 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4023     # check output
 4024     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4025     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4026     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4027     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4028     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4029     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4030     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4031     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4032     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4033     (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")
 4034     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4036     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4037     (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")
 4038     (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")
 4039     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4040     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4041     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4042     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4043     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4044     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4045     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4046     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4047     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4048     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4049     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4050     # . epilogue
 4051     89/<- %esp 5/r32/ebp
 4052     5d/pop-to-ebp
 4053     c3/return
 4054 
 4055 test-convert-function-with-branches-and-local-vars:
 4056     # A conditional 'break' after a 'var' in a block is converted into a
 4057     # nested block that performs all necessary cleanup before jumping. This
 4058     # results in some ugly code duplication.
 4059     # . prologue
 4060     55/push-ebp
 4061     89/<- %ebp 4/r32/esp
 4062     # setup
 4063     (clear-stream _test-input-stream)
 4064     (clear-stream $_test-input-buffered-file->buffer)
 4065     (clear-stream _test-output-stream)
 4066     (clear-stream $_test-output-buffered-file->buffer)
 4067     #
 4068     (write _test-input-stream "fn foo {\n")
 4069     (write _test-input-stream "  {\n")
 4070     (write _test-input-stream "    var x: int\n")
 4071     (write _test-input-stream "    break-if->=\n")
 4072     (write _test-input-stream "    increment x\n")
 4073     (write _test-input-stream "  }\n")
 4074     (write _test-input-stream "}\n")
 4075     # convert
 4076     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4077     (flush _test-output-buffered-file)
 4078 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4084     # check output
 4085     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4086     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4087     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4088     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4089     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4090     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4091     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4092     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4093     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4094     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4095     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4096     (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")
 4097     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4098     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4099     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4100     (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")
 4101     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4102     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4103     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4104     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4105     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4106     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4107     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4108     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4109     # . epilogue
 4110     89/<- %esp 5/r32/ebp
 4111     5d/pop-to-ebp
 4112     c3/return
 4113 
 4114 test-convert-function-with-conditional-loops-and-local-vars:
 4115     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4116     # block that performs all necessary cleanup before jumping. This results
 4117     # in some ugly code duplication.
 4118     # . prologue
 4119     55/push-ebp
 4120     89/<- %ebp 4/r32/esp
 4121     # setup
 4122     (clear-stream _test-input-stream)
 4123     (clear-stream $_test-input-buffered-file->buffer)
 4124     (clear-stream _test-output-stream)
 4125     (clear-stream $_test-output-buffered-file->buffer)
 4126     #
 4127     (write _test-input-stream "fn foo {\n")
 4128     (write _test-input-stream "  {\n")
 4129     (write _test-input-stream "    var x: int\n")
 4130     (write _test-input-stream "    loop-if->=\n")
 4131     (write _test-input-stream "    increment x\n")
 4132     (write _test-input-stream "  }\n")
 4133     (write _test-input-stream "}\n")
 4134     # convert
 4135     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4136     (flush _test-output-buffered-file)
 4137 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4143     # check output
 4144     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4145     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4146     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4147     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4148     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4149     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4150     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 4151     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 4152     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 4153     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 4154     (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")
 4155     (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")
 4156     (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")
 4157     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 4158     (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")
 4159     (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")
 4160     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 4161     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 4162     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 4163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 4164     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 4165     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 4166     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 4167     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 4168     # . epilogue
 4169     89/<- %esp 5/r32/ebp
 4170     5d/pop-to-ebp
 4171     c3/return
 4172 
 4173 test-convert-function-with-unconditional-loops-and-local-vars:
 4174     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 4175     # regular block cleanup. Any instructions after 'loop' are dead and
 4176     # therefore skipped.
 4177     # . prologue
 4178     55/push-ebp
 4179     89/<- %ebp 4/r32/esp
 4180     # setup
 4181     (clear-stream _test-input-stream)
 4182     (clear-stream $_test-input-buffered-file->buffer)
 4183     (clear-stream _test-output-stream)
 4184     (clear-stream $_test-output-buffered-file->buffer)
 4185     #
 4186     (write _test-input-stream "fn foo {\n")
 4187     (write _test-input-stream "  {\n")
 4188     (write _test-input-stream "    var x: int\n")
 4189     (write _test-input-stream "    loop\n")
 4190     (write _test-input-stream "    increment x\n")
 4191     (write _test-input-stream "  }\n")
 4192     (write _test-input-stream "}\n")
 4193     # convert
 4194     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4195     (flush _test-output-buffered-file)
 4196 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4202     # check output
 4203     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 4204     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 4205     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 4206     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 4207     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 4208     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 4209     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 4210     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 4211     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 4212     (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")
 4213     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 4214     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 4215     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 4216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 4217     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 4218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 4219     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 4220     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 4221     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 4222     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 4223     # . epilogue
 4224     89/<- %esp 5/r32/ebp
 4225     5d/pop-to-ebp
 4226     c3/return
 4227 
 4228 test-convert-function-with-branches-and-loops-and-local-vars:
 4229     # . prologue
 4230     55/push-ebp
 4231     89/<- %ebp 4/r32/esp
 4232     # setup
 4233     (clear-stream _test-input-stream)
 4234     (clear-stream $_test-input-buffered-file->buffer)
 4235     (clear-stream _test-output-stream)
 4236     (clear-stream $_test-output-buffered-file->buffer)
 4237     #
 4238     (write _test-input-stream "fn foo {\n")
 4239     (write _test-input-stream "  {\n")
 4240     (write _test-input-stream "    var x: int\n")
 4241     (write _test-input-stream "    break-if->=\n")
 4242     (write _test-input-stream "    increment x\n")
 4243     (write _test-input-stream "    loop\n")
 4244     (write _test-input-stream "  }\n")
 4245     (write _test-input-stream "}\n")
 4246     # convert
 4247     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4248     (flush _test-output-buffered-file)
 4249 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4255     # check output
 4256     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4257     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4258     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4259     (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")
 4260     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4261     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4262     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4263     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4264     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4265     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4266     (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")
 4267     (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")
 4268     (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")
 4269     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 4270     (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")
 4271     (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")
 4272     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 4273     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 4274     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 4275     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 4276     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 4277     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 4278     (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")
 4279     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 4280     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 4281     # . epilogue
 4282     89/<- %esp 5/r32/ebp
 4283     5d/pop-to-ebp
 4284     c3/return
 4285 
 4286 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 4287     # . prologue
 4288     55/push-ebp
 4289     89/<- %ebp 4/r32/esp
 4290     # setup
 4291     (clear-stream _test-input-stream)
 4292     (clear-stream $_test-input-buffered-file->buffer)
 4293     (clear-stream _test-output-stream)
 4294     (clear-stream $_test-output-buffered-file->buffer)
 4295     #
 4296     (write _test-input-stream "fn foo {\n")
 4297     (write _test-input-stream "  a: {\n")
 4298     (write _test-input-stream "    var x: int\n")
 4299     (write _test-input-stream "    {\n")
 4300     (write _test-input-stream "      var y: int\n")
 4301     (write _test-input-stream "      break-if->= a\n")
 4302     (write _test-input-stream "      increment x\n")
 4303     (write _test-input-stream "      loop\n")
 4304     (write _test-input-stream "    }\n")
 4305     (write _test-input-stream "  }\n")
 4306     (write _test-input-stream "}\n")
 4307     # convert
 4308     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4309     (flush _test-output-buffered-file)
 4310 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4316     # check output
 4317     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 4318     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 4319     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 4320     (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")
 4321     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 4322     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 4323     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 4324     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 4325     (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")
 4326     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 4327     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 4328     (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")
 4329     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 4330     (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")
 4331     (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")
 4332     (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")
 4333     (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")
 4334     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 4335     (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")
 4336     (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")
 4337     (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")
 4338     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 4339     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 4340     (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")
 4341     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 4342     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 4343     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 4344     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 4345     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 4346     (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")
 4347     (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")
 4348     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 4349     # . epilogue
 4350     89/<- %esp 5/r32/ebp
 4351     5d/pop-to-ebp
 4352     c3/return
 4353 
 4354 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 4355     # . prologue
 4356     55/push-ebp
 4357     89/<- %ebp 4/r32/esp
 4358     # setup
 4359     (clear-stream _test-input-stream)
 4360     (clear-stream $_test-input-buffered-file->buffer)
 4361     (clear-stream _test-output-stream)
 4362     (clear-stream $_test-output-buffered-file->buffer)
 4363     # non-local conditional branch from a block without a local variable,
 4364     # unwinding a local on the stack
 4365     (write _test-input-stream "fn foo {\n")
 4366     (write _test-input-stream "  a: {\n")
 4367     (write _test-input-stream "    var x: int\n")
 4368     (write _test-input-stream "    {\n")
 4369     (write _test-input-stream "      break-if->= a\n")
 4370     (write _test-input-stream "    }\n")
 4371     (write _test-input-stream "  }\n")
 4372     (write _test-input-stream "}\n")
 4373     # convert
 4374     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4375     (flush _test-output-buffered-file)
 4376 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4382     # check output
 4383     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 4384     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 4385     (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")
 4386     (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")
 4387     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 4388     (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")
 4389     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 4390     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 4391     (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")
 4392     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 4393     (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")
 4394     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 4395     (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")
 4396     (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")
 4397     (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")
 4398     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 4399     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 4400     (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")
 4401     (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")
 4402     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 4403     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 4404     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 4405     (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")
 4406     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 4407     (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")
 4408     (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")
 4409     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 4410     # . epilogue
 4411     89/<- %esp 5/r32/ebp
 4412     5d/pop-to-ebp
 4413     c3/return
 4414 
 4415 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 4416     # . prologue
 4417     55/push-ebp
 4418     89/<- %ebp 4/r32/esp
 4419     # setup
 4420     (clear-stream _test-input-stream)
 4421     (clear-stream $_test-input-buffered-file->buffer)
 4422     (clear-stream _test-output-stream)
 4423     (clear-stream $_test-output-buffered-file->buffer)
 4424     # non-local unconditional branch from a block without a local variable,
 4425     # unwinding a local on the stack
 4426     (write _test-input-stream "fn foo {\n")
 4427     (write _test-input-stream "  a: {\n")
 4428     (write _test-input-stream "    var x: int\n")
 4429     (write _test-input-stream "    {\n")
 4430     (write _test-input-stream "      break a\n")
 4431     (write _test-input-stream "    }\n")
 4432     (write _test-input-stream "  }\n")
 4433     (write _test-input-stream "}\n")
 4434     # convert
 4435     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4436     (flush _test-output-buffered-file)
 4437 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4443     # check output
 4444     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 4445     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 4446     (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")
 4447     (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")
 4448     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 4449     (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")
 4450     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 4451     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 4452     (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")
 4453     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 4454     (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")
 4455     (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")
 4456     (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")
 4457     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 4458     (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")
 4459     (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")
 4460     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 4461     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 4462     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 4463     (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")
 4464     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 4465     (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")
 4466     (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")
 4467     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 4468     # . epilogue
 4469     89/<- %esp 5/r32/ebp
 4470     5d/pop-to-ebp
 4471     c3/return
 4472 
 4473 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 4474     # . prologue
 4475     55/push-ebp
 4476     89/<- %ebp 4/r32/esp
 4477     # setup
 4478     (clear-stream _test-input-stream)
 4479     (clear-stream $_test-input-buffered-file->buffer)
 4480     (clear-stream _test-output-stream)
 4481     (clear-stream $_test-output-buffered-file->buffer)
 4482     #
 4483     (write _test-input-stream "fn foo {\n")
 4484     (write _test-input-stream "  a: {\n")
 4485     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 4486     (write _test-input-stream "    {\n")
 4487     (write _test-input-stream "      break a\n")
 4488     (write _test-input-stream "    }\n")
 4489     (write _test-input-stream "  }\n")
 4490     (write _test-input-stream "}\n")
 4491     # convert
 4492     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4493     (flush _test-output-buffered-file)
 4494 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4500     # check output
 4501     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 4502     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 4503     (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")
 4504     (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")
 4505     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 4506     (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")
 4507     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 4508     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 4509     (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")
 4510     (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")
 4511     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 4512     (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")
 4513     (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")
 4514     (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")
 4515     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 4516     (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")
 4517     (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")
 4518     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 4519     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 4520     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 4521     (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")
 4522     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 4523     (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")
 4524     (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")
 4525     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 4526     # . epilogue
 4527     89/<- %esp 5/r32/ebp
 4528     5d/pop-to-ebp
 4529     c3/return
 4530 
 4531 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 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     #
 4541     (write _test-input-stream "fn foo {\n")
 4542     (write _test-input-stream "  a: {\n")
 4543     (write _test-input-stream "    var x: int\n")
 4544     (write _test-input-stream "    {\n")
 4545     (write _test-input-stream "      var y: int\n")
 4546     (write _test-input-stream "      break a\n")
 4547     (write _test-input-stream "      increment x\n")
 4548     (write _test-input-stream "    }\n")
 4549     (write _test-input-stream "  }\n")
 4550     (write _test-input-stream "}\n")
 4551     # convert
 4552     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4553     (flush _test-output-buffered-file)
 4554 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4560     # check output
 4561     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 4562     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 4563     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 4564     (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")
 4565     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 4566     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 4567     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 4568     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 4569     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 4570     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 4571     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 4572     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 4573     (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")
 4574     (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")
 4575     (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")
 4576     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 4577     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 4578     (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")
 4579     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 4580     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 4581     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 4582     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 4583     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 4584     (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")
 4585     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 4586     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 4587     # . epilogue
 4588     89/<- %esp 5/r32/ebp
 4589     5d/pop-to-ebp
 4590     c3/return
 4591 
 4592 test-convert-function-with-unconditional-break-and-local-vars:
 4593     # . prologue
 4594     55/push-ebp
 4595     89/<- %ebp 4/r32/esp
 4596     # setup
 4597     (clear-stream _test-input-stream)
 4598     (clear-stream $_test-input-buffered-file->buffer)
 4599     (clear-stream _test-output-stream)
 4600     (clear-stream $_test-output-buffered-file->buffer)
 4601     #
 4602     (write _test-input-stream "fn foo {\n")
 4603     (write _test-input-stream "  {\n")
 4604     (write _test-input-stream "    var x: int\n")
 4605     (write _test-input-stream "    {\n")
 4606     (write _test-input-stream "      var y: int\n")
 4607     (write _test-input-stream "      break\n")
 4608     (write _test-input-stream "      increment x\n")
 4609     (write _test-input-stream "    }\n")
 4610     (write _test-input-stream "  }\n")
 4611     (write _test-input-stream "}\n")
 4612     # convert
 4613     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4614     (flush _test-output-buffered-file)
 4615 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4621     # check output
 4622     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 4623     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 4624     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 4625     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 4626     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 4627     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 4628     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 4629     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 4630     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 4631     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 4632     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 4633     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 4634     (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")
 4635     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 4636     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 4637     (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")
 4638     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 4639     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 4640     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 4641     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 4642     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 4643     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 4644     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 4645     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 4646     # . epilogue
 4647     89/<- %esp 5/r32/ebp
 4648     5d/pop-to-ebp
 4649     c3/return
 4650 
 4651 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 4652     # . prologue
 4653     55/push-ebp
 4654     89/<- %ebp 4/r32/esp
 4655     # setup
 4656     (clear-stream _test-input-stream)
 4657     (clear-stream $_test-input-buffered-file->buffer)
 4658     (clear-stream _test-output-stream)
 4659     (clear-stream $_test-output-buffered-file->buffer)
 4660     #
 4661     (write _test-input-stream "fn foo {\n")
 4662     (write _test-input-stream "  a: {\n")
 4663     (write _test-input-stream "    var x: int\n")
 4664     (write _test-input-stream "    {\n")
 4665     (write _test-input-stream "      var y: int\n")
 4666     (write _test-input-stream "      loop a\n")
 4667     (write _test-input-stream "      increment x\n")
 4668     (write _test-input-stream "    }\n")
 4669     (write _test-input-stream "  }\n")
 4670     (write _test-input-stream "}\n")
 4671     # convert
 4672     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4673     (flush _test-output-buffered-file)
 4674 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4680     # check output
 4681     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 4682     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 4683     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 4684     (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")
 4685     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 4686     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 4687     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 4688     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 4689     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 4690     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 4691     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 4692     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 4693     (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")
 4694     (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")
 4695     (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")
 4696     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 4697     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 4698     (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")
 4699     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 4700     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 4701     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 4702     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 4703     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 4704     (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")
 4705     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 4706     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 4707     # . epilogue
 4708     89/<- %esp 5/r32/ebp
 4709     5d/pop-to-ebp
 4710     c3/return
 4711 
 4712 test-convert-function-with-local-array-var-in-mem:
 4713     # . prologue
 4714     55/push-ebp
 4715     89/<- %ebp 4/r32/esp
 4716     # setup
 4717     (clear-stream _test-input-stream)
 4718     (clear-stream $_test-input-buffered-file->buffer)
 4719     (clear-stream _test-output-stream)
 4720     (clear-stream $_test-output-buffered-file->buffer)
 4721     #
 4722     (write _test-input-stream "fn foo {\n")
 4723     (write _test-input-stream "  var x: (array int 3)\n")
 4724     (write _test-input-stream "}\n")
 4725     # convert
 4726     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4727     (flush _test-output-buffered-file)
 4728 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4734     # check output
 4735     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 4736     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 4737     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 4738     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 4739     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 4740     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 4741     # define x
 4742     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 4743     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 4744     # reclaim x
 4745     (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")
 4746     #
 4747     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 4748     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 4749     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 4750     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 4751     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 4752     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 4753     # . epilogue
 4754     89/<- %esp 5/r32/ebp
 4755     5d/pop-to-ebp
 4756     c3/return
 4757 
 4758 test-array-size-in-hex:
 4759     # . prologue
 4760     55/push-ebp
 4761     89/<- %ebp 4/r32/esp
 4762     # setup
 4763     (clear-stream _test-input-stream)
 4764     (clear-stream $_test-input-buffered-file->buffer)
 4765     (clear-stream _test-output-stream)
 4766     (clear-stream $_test-output-buffered-file->buffer)
 4767     (clear-stream _test-error-stream)
 4768     (clear-stream $_test-error-buffered-file->buffer)
 4769     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4770     68/push 0/imm32
 4771     68/push 0/imm32
 4772     89/<- %edx 4/r32/esp
 4773     (tailor-exit-descriptor %edx 0x10)
 4774     #
 4775     (write _test-input-stream "fn foo {\n")
 4776     (write _test-input-stream "  var x: (array int 10)\n")
 4777     (write _test-input-stream "}\n")
 4778     # convert
 4779     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4780     # registers except esp clobbered at this point
 4781     # restore ed
 4782     89/<- %edx 4/r32/esp
 4783     (flush _test-output-buffered-file)
 4784     (flush _test-error-buffered-file)
 4785 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4791     # check output
 4792     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 4793     (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")
 4794     # check that stop(1) was called
 4795     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 4796     # don't restore from ebp
 4797     81 0/subop/add %esp 8/imm32
 4798     # . epilogue
 4799     5d/pop-to-ebp
 4800     c3/return
 4801 
 4802 test-convert-function-with-populate:
 4803     # . prologue
 4804     55/push-ebp
 4805     89/<- %ebp 4/r32/esp
 4806     # setup
 4807     (clear-stream _test-input-stream)
 4808     (clear-stream $_test-input-buffered-file->buffer)
 4809     (clear-stream _test-output-stream)
 4810     (clear-stream $_test-output-buffered-file->buffer)
 4811     #
 4812     (write _test-input-stream "fn foo {\n")
 4813     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 4814     (write _test-input-stream "  populate x, 7\n")
 4815     (write _test-input-stream "}\n")
 4816     # convert
 4817     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4818     (flush _test-output-buffered-file)
 4819 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4825     # check output
 4826     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 4827     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 4828     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 4829     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 4830     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 4831     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 4832     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 4833     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 4834     (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)
 4835     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 4836     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 4837     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 4838     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 4839     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 4840     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 4841     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 4842     # . epilogue
 4843     89/<- %esp 5/r32/ebp
 4844     5d/pop-to-ebp
 4845     c3/return
 4846 
 4847 # special-case for size(byte) when allocating array
 4848 test-convert-function-with-local-array-of-bytes-in-mem:
 4849     # . prologue
 4850     55/push-ebp
 4851     89/<- %ebp 4/r32/esp
 4852     # setup
 4853     (clear-stream _test-input-stream)
 4854     (clear-stream $_test-input-buffered-file->buffer)
 4855     (clear-stream _test-output-stream)
 4856     (clear-stream $_test-output-buffered-file->buffer)
 4857     #
 4858     (write _test-input-stream "fn foo {\n")
 4859     (write _test-input-stream "  var x: (array byte 3)\n")
 4860     (write _test-input-stream "}\n")
 4861     # convert
 4862     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4863     (flush _test-output-buffered-file)
 4864 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4870     # check output
 4871     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 4872     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 4873     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 4874     (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")
 4875     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 4876     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 4877     # define x
 4878     (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")
 4879     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 4880     # reclaim x
 4881     (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")
 4882     #
 4883     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 4884     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 4885     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 4886     (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")
 4887     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 4888     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 4889     # . epilogue
 4890     89/<- %esp 5/r32/ebp
 4891     5d/pop-to-ebp
 4892     c3/return
 4893 
 4894 test-convert-address:
 4895     # . prologue
 4896     55/push-ebp
 4897     89/<- %ebp 4/r32/esp
 4898     # setup
 4899     (clear-stream _test-input-stream)
 4900     (clear-stream $_test-input-buffered-file->buffer)
 4901     (clear-stream _test-output-stream)
 4902     (clear-stream $_test-output-buffered-file->buffer)
 4903     #
 4904     (write _test-input-stream "fn foo {\n")
 4905     (write _test-input-stream "  var a: int\n")
 4906     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 4907     (write _test-input-stream "}\n")
 4908     # convert
 4909     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4910     (flush _test-output-buffered-file)
 4911 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4917     # check output
 4918     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 4919     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 4920     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 4921     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 4922     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 4923     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 4924     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 4925     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 4926     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 4927     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 4928     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 4929     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 4930     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 4931     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 4932     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 4933     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 4934     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 4935     # . epilogue
 4936     89/<- %esp 5/r32/ebp
 4937     5d/pop-to-ebp
 4938     c3/return
 4939 
 4940 test-convert-floating-point-convert:
 4941     # . prologue
 4942     55/push-ebp
 4943     89/<- %ebp 4/r32/esp
 4944     # setup
 4945     (clear-stream _test-input-stream)
 4946     (clear-stream $_test-input-buffered-file->buffer)
 4947     (clear-stream _test-output-stream)
 4948     (clear-stream $_test-output-buffered-file->buffer)
 4949     #
 4950     (write _test-input-stream "fn foo {\n")
 4951     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4952     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4953     (write _test-input-stream "}\n")
 4954     # convert
 4955     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4956     (flush _test-output-buffered-file)
 4957 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4963     # check output
 4964     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 4965     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 4966     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 4967     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 4968     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 4969     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 4970     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 4971     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 4972     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 4973     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 4974     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 4975     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 4976     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 4977     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 4978     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 4979     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 4980     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 4981     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 4982     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 4983     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 4984     # . epilogue
 4985     89/<- %esp 5/r32/ebp
 4986     5d/pop-to-ebp
 4987     c3/return
 4988 
 4989 test-convert-floating-point-convert-2:
 4990     # . prologue
 4991     55/push-ebp
 4992     89/<- %ebp 4/r32/esp
 4993     # setup
 4994     (clear-stream _test-input-stream)
 4995     (clear-stream $_test-input-buffered-file->buffer)
 4996     (clear-stream _test-output-stream)
 4997     (clear-stream $_test-output-buffered-file->buffer)
 4998     #
 4999     (write _test-input-stream "fn foo {\n")
 5000     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5001     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5002     (write _test-input-stream "  a <- convert b\n")
 5003     (write _test-input-stream "}\n")
 5004     # convert
 5005     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5006     (flush _test-output-buffered-file)
 5007 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5013     # check output
 5014     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5015     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5016     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5017     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5018     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5019     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5020     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5021     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5022     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5023     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5024     (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")
 5025     (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")
 5026     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5027     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5028     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5029     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5030     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5031     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5032     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5033     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5034     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5035     # . epilogue
 5036     89/<- %esp 5/r32/ebp
 5037     5d/pop-to-ebp
 5038     c3/return
 5039 
 5040 test-convert-floating-point-operation:
 5041     # . prologue
 5042     55/push-ebp
 5043     89/<- %ebp 4/r32/esp
 5044     # setup
 5045     (clear-stream _test-input-stream)
 5046     (clear-stream $_test-input-buffered-file->buffer)
 5047     (clear-stream _test-output-stream)
 5048     (clear-stream $_test-output-buffered-file->buffer)
 5049     #
 5050     (write _test-input-stream "fn f {\n")
 5051     (write _test-input-stream "  var m: float\n")
 5052     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5053     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5054     (write _test-input-stream "  x <- copy y\n")
 5055     (write _test-input-stream "  copy-to m, y\n")
 5056     (write _test-input-stream "  x <- add y\n")
 5057     (write _test-input-stream "  x <- add m\n")
 5058     (write _test-input-stream "  x <- subtract y\n")
 5059     (write _test-input-stream "  x <- subtract m\n")
 5060     (write _test-input-stream "  x <- multiply y\n")
 5061     (write _test-input-stream "  x <- multiply m\n")
 5062     (write _test-input-stream "  x <- divide y\n")
 5063     (write _test-input-stream "  x <- divide m\n")
 5064     (write _test-input-stream "  x <- reciprocal y\n")
 5065     (write _test-input-stream "  x <- reciprocal m\n")
 5066     (write _test-input-stream "  x <- square-root y\n")
 5067     (write _test-input-stream "  x <- square-root m\n")
 5068     (write _test-input-stream "  x <- inverse-square-root y\n")
 5069     (write _test-input-stream "  x <- inverse-square-root m\n")
 5070     (write _test-input-stream "  x <- max y\n")
 5071     (write _test-input-stream "  x <- max m\n")
 5072     (write _test-input-stream "  x <- min y\n")
 5073     (write _test-input-stream "  x <- min m\n")
 5074     (write _test-input-stream "  compare x, y\n")
 5075     (write _test-input-stream "  compare x, m\n")
 5076     (write _test-input-stream "}\n")
 5077     # convert
 5078     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5079     (flush _test-output-buffered-file)
 5080 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5086     # check output
 5087     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5088     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5089     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5090     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5091     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5092     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5093     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5094     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5095     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5096     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5097     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5098     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5099     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5100     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5101     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5102     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5103     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5104     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5105     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5106     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5107     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5108     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5109     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5110     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5111     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5112     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5113     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5114     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5115     (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")
 5116     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5117     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5118     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5119     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5120     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 5121     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5122     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 5123     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 5124     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 5125     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 5126     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 5127     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 5128     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 5129     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 5130     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 5131     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 5132     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 5133     # . epilogue
 5134     89/<- %esp 5/r32/ebp
 5135     5d/pop-to-ebp
 5136     c3/return
 5137 
 5138 test-convert-floating-point-dereferenced:
 5139     # . prologue
 5140     55/push-ebp
 5141     89/<- %ebp 4/r32/esp
 5142     # setup
 5143     (clear-stream _test-input-stream)
 5144     (clear-stream $_test-input-buffered-file->buffer)
 5145     (clear-stream _test-output-stream)
 5146     (clear-stream $_test-output-buffered-file->buffer)
 5147     #
 5148     (write _test-input-stream "fn f {\n")
 5149     (write _test-input-stream "  var m: float\n")
 5150     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5151     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 5152     (write _test-input-stream "  x <- multiply *y\n")
 5153     (write _test-input-stream "}\n")
 5154     # convert
 5155     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5156     (flush _test-output-buffered-file)
 5157 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5163     # check output
 5164     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 5165     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 5166     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 5167     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 5168     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 5169     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 5170     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 5171     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 5172     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 5173     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 5174     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 5175     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 5176     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 5177     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 5178     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 5179     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 5180     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 5181     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 5182     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 5183     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 5184     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 5185     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 5186     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 5187     # . epilogue
 5188     89/<- %esp 5/r32/ebp
 5189     5d/pop-to-ebp
 5190     c3/return
 5191 
 5192 test-convert-length-of-array:
 5193     # . prologue
 5194     55/push-ebp
 5195     89/<- %ebp 4/r32/esp
 5196     # setup
 5197     (clear-stream _test-input-stream)
 5198     (clear-stream $_test-input-buffered-file->buffer)
 5199     (clear-stream _test-output-stream)
 5200     (clear-stream $_test-output-buffered-file->buffer)
 5201     #
 5202     (write _test-input-stream "fn foo a: (addr array int) {\n")
 5203     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 5204     (write _test-input-stream "  var c/eax: int <- length b\n")
 5205     (write _test-input-stream "}\n")
 5206     # convert
 5207     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5208     (flush _test-output-buffered-file)
 5209 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5215     # check output
 5216     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 5217     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 5218     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 5219     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 5220     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 5221     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 5222     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 5223     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 5224     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 5225     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 5226     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 5227     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 5228     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 5229     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 5230     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 5231     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 5232     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 5233     # . epilogue
 5234     89/<- %esp 5/r32/ebp
 5235     5d/pop-to-ebp
 5236     c3/return
 5237 
 5238 # special-case for size(byte) when computing array length
 5239 test-convert-length-of-array-of-bytes:
 5240     # . prologue
 5241     55/push-ebp
 5242     89/<- %ebp 4/r32/esp
 5243     # setup
 5244     (clear-stream _test-input-stream)
 5245     (clear-stream $_test-input-buffered-file->buffer)
 5246     (clear-stream _test-output-stream)
 5247     (clear-stream $_test-output-buffered-file->buffer)
 5248     #
 5249     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 5250     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 5251     (write _test-input-stream "  var c/eax: int <- length b\n")
 5252     (write _test-input-stream "}\n")
 5253     # convert
 5254     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5255     (flush _test-output-buffered-file)
 5256 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5262     # check output
 5263     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 5264     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 5265     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 5266     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 5267     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 5268     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 5269     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 5270     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 5271     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 5272     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 5273     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 5274     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 5275     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 5276     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 5277     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 5278     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 5279     # . epilogue
 5280     89/<- %esp 5/r32/ebp
 5281     5d/pop-to-ebp
 5282     c3/return
 5283 
 5284 test-convert-length-of-array-on-stack:
 5285     # . prologue
 5286     55/push-ebp
 5287     89/<- %ebp 4/r32/esp
 5288     # setup
 5289     (clear-stream _test-input-stream)
 5290     (clear-stream $_test-input-buffered-file->buffer)
 5291     (clear-stream _test-output-stream)
 5292     (clear-stream $_test-output-buffered-file->buffer)
 5293     #
 5294     (write _test-input-stream "fn foo {\n")
 5295     (write _test-input-stream "  var a: (array int 3)\n")
 5296     (write _test-input-stream "  var b/eax: int <- length a\n")
 5297     (write _test-input-stream "}\n")
 5298     # convert
 5299     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5300     (flush _test-output-buffered-file)
 5301 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5307     # check output
 5308     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 5309     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 5310     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 5311     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 5312     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 5313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 5314     # define x
 5315     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 5316     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 5317     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 5318     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 5319     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 5320     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 5321     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 5322     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 5323     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 5324     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 5325     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 5326     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 5327     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 5328     # . epilogue
 5329     89/<- %esp 5/r32/ebp
 5330     5d/pop-to-ebp
 5331     c3/return
 5332 
 5333 test-reg-var-def-with-read-of-same-register:
 5334     # . prologue
 5335     55/push-ebp
 5336     89/<- %ebp 4/r32/esp
 5337     # setup
 5338     (clear-stream _test-input-stream)
 5339     (clear-stream $_test-input-buffered-file->buffer)
 5340     (clear-stream _test-output-stream)
 5341     (clear-stream $_test-output-buffered-file->buffer)
 5342     (clear-stream _test-error-stream)
 5343     (clear-stream $_test-error-buffered-file->buffer)
 5344     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 5345     68/push 0/imm32
 5346     68/push 0/imm32
 5347     89/<- %edx 4/r32/esp
 5348     (tailor-exit-descriptor %edx 0x10)
 5349     #
 5350     (write _test-input-stream "fn foo {\n")
 5351     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5352     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5353     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5354     (write _test-input-stream "}\n")
 5355     # convert
 5356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5357     # registers except esp could be clobbered at this point (though they shouldn't be)
 5358     # restore ed
 5359     89/<- %edx 4/r32/esp
 5360     (flush _test-output-buffered-file)
 5361     (flush _test-error-buffered-file)
 5362 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5368 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5374     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 5375     # check output
 5376     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 5377     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 5378     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 5379     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 5380     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 5381     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 5382     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 5383     (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")
 5384     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-reg-var-def-with-read-of-same-register/8")
 5385     (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")
 5386     (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")
 5387     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-reg-var-def-with-read-of-same-register/13")
 5388     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/14")
 5389     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/15")
 5390     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/16")
 5391     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/17")
 5392     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/18")
 5393     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/19")
 5394     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/20")
 5395     # don't restore from ebp
 5396     81 0/subop/add %esp 8/imm32
 5397     # . epilogue
 5398     5d/pop-to-ebp
 5399     c3/return
 5400 
 5401 test-convert-index-into-array:
 5402     # . prologue
 5403     55/push-ebp
 5404     89/<- %ebp 4/r32/esp
 5405     # setup
 5406     (clear-stream _test-input-stream)
 5407     (clear-stream $_test-input-buffered-file->buffer)
 5408     (clear-stream _test-output-stream)
 5409     (clear-stream $_test-output-buffered-file->buffer)
 5410     #
 5411     (write _test-input-stream "fn foo {\n")
 5412     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5413     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5414     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5415     (write _test-input-stream "}\n")
 5416     # convert
 5417     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5418     (flush _test-output-buffered-file)
 5419 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5425     # check output
 5426     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 5427     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 5428     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 5429     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 5430     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 5431     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 5432     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 5433     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 5434     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 5435     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 5436     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/10")
 5437     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/11")
 5438     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/12")
 5439     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/13")
 5440     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/14")
 5441     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/15")
 5442     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/16")
 5443     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/17")
 5444     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/18")
 5445     # . epilogue
 5446     89/<- %esp 5/r32/ebp
 5447     5d/pop-to-ebp
 5448     c3/return
 5449 
 5450 test-convert-index-into-array-of-bytes:
 5451     # . prologue
 5452     55/push-ebp
 5453     89/<- %ebp 4/r32/esp
 5454     # setup
 5455     (clear-stream _test-input-stream)
 5456     (clear-stream $_test-input-buffered-file->buffer)
 5457     (clear-stream _test-output-stream)
 5458     (clear-stream $_test-output-buffered-file->buffer)
 5459     #
 5460     (write _test-input-stream "fn foo {\n")
 5461     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5462     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5463     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 5464     (write _test-input-stream "}\n")
 5465     # convert
 5466     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5467     (flush _test-output-buffered-file)
 5468 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5474     # check output
 5475     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 5476     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 5477     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 5478     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 5479     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 5480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 5481     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 5482     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 5483     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 5484     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 5485     (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")
 5486     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/13")
 5487     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/14")
 5488     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/15")
 5489     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/16")
 5490     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/17")
 5491     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/18")
 5492     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/19")
 5493     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/20")
 5494     # . epilogue
 5495     89/<- %esp 5/r32/ebp
 5496     5d/pop-to-ebp
 5497     c3/return
 5498 
 5499 test-convert-index-into-array-with-literal:
 5500     # . prologue
 5501     55/push-ebp
 5502     89/<- %ebp 4/r32/esp
 5503     # setup
 5504     (clear-stream _test-input-stream)
 5505     (clear-stream $_test-input-buffered-file->buffer)
 5506     (clear-stream _test-output-stream)
 5507     (clear-stream $_test-output-buffered-file->buffer)
 5508     #
 5509     (write _test-input-stream "fn foo {\n")
 5510     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5511     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 5512     (write _test-input-stream "}\n")
 5513     # convert
 5514     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5515     (flush _test-output-buffered-file)
 5516 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5522     # check output
 5523     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 5524     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 5525     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 5526     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 5527     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 5528     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 5529     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 5530     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 5531                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 5532     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/8")
 5533     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/9")
 5534     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/10")
 5535     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/11")
 5536     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/12")
 5537     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/13")
 5538     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/14")
 5539     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/15")
 5540     # . epilogue
 5541     89/<- %esp 5/r32/ebp
 5542     5d/pop-to-ebp
 5543     c3/return
 5544 
 5545 test-convert-index-into-array-of-bytes-with-literal:
 5546     # . prologue
 5547     55/push-ebp
 5548     89/<- %ebp 4/r32/esp
 5549     # setup
 5550     (clear-stream _test-input-stream)
 5551     (clear-stream $_test-input-buffered-file->buffer)
 5552     (clear-stream _test-output-stream)
 5553     (clear-stream $_test-output-buffered-file->buffer)
 5554     #
 5555     (write _test-input-stream "fn foo {\n")
 5556     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5557     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 5558     (write _test-input-stream "}\n")
 5559     # convert
 5560     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5561     (flush _test-output-buffered-file)
 5562 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5568     # check output
 5569     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 5570     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 5571     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 5572     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 5573     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 5574     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 5575     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 5576     (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")
 5577                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 5578     (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")
 5579     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 5580     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 5581     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 5582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 5583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 5584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 5585     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 5586     # . epilogue
 5587     89/<- %esp 5/r32/ebp
 5588     5d/pop-to-ebp
 5589     c3/return
 5590 
 5591 test-convert-index-into-array-on-stack:
 5592     # . prologue
 5593     55/push-ebp
 5594     89/<- %ebp 4/r32/esp
 5595     # setup
 5596     (clear-stream _test-input-stream)
 5597     (clear-stream $_test-input-buffered-file->buffer)
 5598     (clear-stream _test-output-stream)
 5599     (clear-stream $_test-output-buffered-file->buffer)
 5600     #
 5601     (write _test-input-stream "fn foo {\n")
 5602     (write _test-input-stream "  var arr: (array int 3)\n")
 5603     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 5604     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5605     (write _test-input-stream "}\n")
 5606     # convert
 5607     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5608     (flush _test-output-buffered-file)
 5609 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5615     # check output
 5616     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 5617     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 5618     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 5619     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 5620     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 5621     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 5622     # var arr
 5623     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 5624     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 5625     # var idx
 5626     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 5627     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 5628     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 5629     (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")
 5630     # reclaim idx
 5631     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/11")
 5632     # reclaim arr
 5633     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/12")
 5634     #
 5635     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/13")
 5636     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/14")
 5637     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/15")
 5638     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/16")
 5639     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/17")
 5640     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/18")
 5641     # . epilogue
 5642     89/<- %esp 5/r32/ebp
 5643     5d/pop-to-ebp
 5644     c3/return
 5645 
 5646 test-convert-index-into-array-on-stack-with-literal:
 5647     # . prologue
 5648     55/push-ebp
 5649     89/<- %ebp 4/r32/esp
 5650     # setup
 5651     (clear-stream _test-input-stream)
 5652     (clear-stream $_test-input-buffered-file->buffer)
 5653     (clear-stream _test-output-stream)
 5654     (clear-stream $_test-output-buffered-file->buffer)
 5655     #
 5656     (write _test-input-stream "fn foo {\n")
 5657     (write _test-input-stream "  var arr: (array int 3)\n")
 5658     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 5659     (write _test-input-stream "}\n")
 5660     # convert
 5661     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5662     (flush _test-output-buffered-file)
 5663 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5669     # check output
 5670     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 5671     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 5672     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 5673     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 5674     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 5675     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 5676     # var arr
 5677     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 5678     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 5679     # var x
 5680     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 5681     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 5682     (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")
 5683     # reclaim x
 5684     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/10")
 5685     # reclaim arr
 5686     (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")
 5687     #
 5688     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/12")
 5689     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/13")
 5690     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/14")
 5691     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/15")
 5692     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/16")
 5693     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/17")
 5694     # . epilogue
 5695     89/<- %esp 5/r32/ebp
 5696     5d/pop-to-ebp
 5697     c3/return
 5698 
 5699 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 5700     # . prologue
 5701     55/push-ebp
 5702     89/<- %ebp 4/r32/esp
 5703     # setup
 5704     (clear-stream _test-input-stream)
 5705     (clear-stream $_test-input-buffered-file->buffer)
 5706     (clear-stream _test-output-stream)
 5707     (clear-stream $_test-output-buffered-file->buffer)
 5708     #
 5709     (write _test-input-stream "fn foo {\n")
 5710     (write _test-input-stream "  var arr: (array byte 3)\n")
 5711     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 5712     (write _test-input-stream "}\n")
 5713     # convert
 5714     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5715     (flush _test-output-buffered-file)
 5716 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5722     # check output
 5723     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 5724     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 5725     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 5726     (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")
 5727     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 5728     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 5729     # var arr
 5730     (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")
 5731     (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")
 5732     # var x
 5733     (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")
 5734     # x is at (ebp-7) + 4 + 2 = ebp-1
 5735     (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")
 5736     # reclaim x
 5737     (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")
 5738     # reclaim arr
 5739     (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")
 5740     #
 5741     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 5742     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 5743     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 5744     (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")
 5745     (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")
 5746     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 5747     # . epilogue
 5748     89/<- %esp 5/r32/ebp
 5749     5d/pop-to-ebp
 5750     c3/return
 5751 
 5752 test-convert-index-into-array-using-offset:
 5753     # . prologue
 5754     55/push-ebp
 5755     89/<- %ebp 4/r32/esp
 5756     # setup
 5757     (clear-stream _test-input-stream)
 5758     (clear-stream $_test-input-buffered-file->buffer)
 5759     (clear-stream _test-output-stream)
 5760     (clear-stream $_test-output-buffered-file->buffer)
 5761     #
 5762     (write _test-input-stream "fn foo {\n")
 5763     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5764     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5765     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5766     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5767     (write _test-input-stream "}\n")
 5768     # convert
 5769     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5770     (flush _test-output-buffered-file)
 5771 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5777     # check output
 5778     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 5779     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 5780     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 5781     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 5782     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 5783     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 5784     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 5785     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 5786     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 5787     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 5788     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 5789     (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")
 5790     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/12")
 5791     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/13")
 5792     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/14")
 5793     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/15")
 5794     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/16")
 5795     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/17")
 5796     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/18")
 5797     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/19")
 5798     # . epilogue
 5799     89/<- %esp 5/r32/ebp
 5800     5d/pop-to-ebp
 5801     c3/return
 5802 
 5803 test-convert-index-into-array-of-bytes-using-offset:
 5804     # . prologue
 5805     55/push-ebp
 5806     89/<- %ebp 4/r32/esp
 5807     # setup
 5808     (clear-stream _test-input-stream)
 5809     (clear-stream $_test-input-buffered-file->buffer)
 5810     (clear-stream _test-output-stream)
 5811     (clear-stream $_test-output-buffered-file->buffer)
 5812     #
 5813     (write _test-input-stream "fn foo {\n")
 5814     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5815     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5816     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5817     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5818     (write _test-input-stream "}\n")
 5819     # convert
 5820     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5821     (flush _test-output-buffered-file)
 5822 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5828     # check output
 5829     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 5830     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 5831     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 5832     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 5833     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 5834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 5835     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 5836     (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")
 5837     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 5838     (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")
 5839     (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")
 5840     (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")
 5841     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/12")
 5842     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 5843     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/14")
 5844     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/15")
 5845     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/16")
 5846     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/17")
 5847     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/18")
 5848     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/19")
 5849     # . epilogue
 5850     89/<- %esp 5/r32/ebp
 5851     5d/pop-to-ebp
 5852     c3/return
 5853 
 5854 test-convert-index-into-array-using-offset-on-stack:
 5855     # . prologue
 5856     55/push-ebp
 5857     89/<- %ebp 4/r32/esp
 5858     # setup
 5859     (clear-stream _test-input-stream)
 5860     (clear-stream $_test-input-buffered-file->buffer)
 5861     (clear-stream _test-output-stream)
 5862     (clear-stream $_test-output-buffered-file->buffer)
 5863     #
 5864     (write _test-input-stream "fn foo {\n")
 5865     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5866     (write _test-input-stream "  var idx: int\n")
 5867     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5868     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5869     (write _test-input-stream "}\n")
 5870     # convert
 5871     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5872     (flush _test-output-buffered-file)
 5873 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5879     # check output
 5880     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 5881     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 5882     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 5883     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 5884     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 5885     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 5886     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 5887     (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")
 5888     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 5889     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 5890     (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")
 5891     (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")
 5892     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/12")
 5893     (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")
 5894     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/14")
 5895     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/15")
 5896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/16")
 5897     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/17")
 5898     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/18")
 5899     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/19")
 5900     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/20")
 5901     # . epilogue
 5902     89/<- %esp 5/r32/ebp
 5903     5d/pop-to-ebp
 5904     c3/return
 5905 
 5906 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 5907     # . prologue
 5908     55/push-ebp
 5909     89/<- %ebp 4/r32/esp
 5910     # setup
 5911     (clear-stream _test-input-stream)
 5912     (clear-stream $_test-input-buffered-file->buffer)
 5913     (clear-stream _test-output-stream)
 5914     (clear-stream $_test-output-buffered-file->buffer)
 5915     #
 5916     (write _test-input-stream "fn foo {\n")
 5917     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5918     (write _test-input-stream "  var idx: int\n")
 5919     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5920     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5921     (write _test-input-stream "}\n")
 5922     # convert
 5923     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5924     (flush _test-output-buffered-file)
 5925 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5931     # check output
 5932     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 5933     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 5934     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 5935     (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")
 5936     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 5937     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 5938     (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")
 5939     (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")
 5940     (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")
 5941     (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")
 5942     (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")
 5943     (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")
 5944     (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")
 5945     (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")
 5946     (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")
 5947     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 5948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 5949     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 5950     (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")
 5951     (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")
 5952     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 5953     # . epilogue
 5954     89/<- %esp 5/r32/ebp
 5955     5d/pop-to-ebp
 5956     c3/return
 5957 
 5958 test-convert-function-and-type-definition:
 5959     # . prologue
 5960     55/push-ebp
 5961     89/<- %ebp 4/r32/esp
 5962     # setup
 5963     (clear-stream _test-input-stream)
 5964     (clear-stream $_test-input-buffered-file->buffer)
 5965     (clear-stream _test-output-stream)
 5966     (clear-stream $_test-output-buffered-file->buffer)
 5967     #
 5968     (write _test-input-stream "fn foo a: (addr t) {\n")
 5969     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 5970     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 5971     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 5972     (write _test-input-stream "}\n")
 5973     (write _test-input-stream "type t {\n")
 5974     (write _test-input-stream "  x: int\n")
 5975     (write _test-input-stream "  y: int\n")
 5976     (write _test-input-stream "}\n")
 5977     # convert
 5978     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5979     (flush _test-output-buffered-file)
 5980 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5986     # check output
 5987     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 5988     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 5989     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 5990     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 5991     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 5992     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 5993     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 5994     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 5995     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 5996     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 5997     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 5998     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 5999     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6000     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6001     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6002     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6003     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6004     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6005     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6006     # . epilogue
 6007     89/<- %esp 5/r32/ebp
 6008     5d/pop-to-ebp
 6009     c3/return
 6010 
 6011 test-type-definition-with-array:
 6012     # . prologue
 6013     55/push-ebp
 6014     89/<- %ebp 4/r32/esp
 6015     # setup
 6016     (clear-stream _test-input-stream)
 6017     (clear-stream $_test-input-buffered-file->buffer)
 6018     (clear-stream _test-output-stream)
 6019     (clear-stream $_test-output-buffered-file->buffer)
 6020     (clear-stream _test-error-stream)
 6021     (clear-stream $_test-error-buffered-file->buffer)
 6022     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6023     68/push 0/imm32
 6024     68/push 0/imm32
 6025     89/<- %edx 4/r32/esp
 6026     (tailor-exit-descriptor %edx 0x10)
 6027     #
 6028     (write _test-input-stream "type t {\n")
 6029     (write _test-input-stream "  a: (array int 3)\n")
 6030     (write _test-input-stream "}\n")
 6031     # convert
 6032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6033     # registers except esp clobbered at this point
 6034     # restore ed
 6035     89/<- %edx 4/r32/esp
 6036     (flush _test-output-buffered-file)
 6037     (flush _test-error-buffered-file)
 6038 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6044     # check output
 6045     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6046     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6047     # check that stop(1) was called
 6048     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6049     # don't restore from ebp
 6050     81 0/subop/add %esp 8/imm32
 6051     # . epilogue
 6052     5d/pop-to-ebp
 6053     c3/return
 6054 
 6055 test-type-definition-with-addr:
 6056     # . prologue
 6057     55/push-ebp
 6058     89/<- %ebp 4/r32/esp
 6059     # setup
 6060     (clear-stream _test-input-stream)
 6061     (clear-stream $_test-input-buffered-file->buffer)
 6062     (clear-stream _test-output-stream)
 6063     (clear-stream $_test-output-buffered-file->buffer)
 6064     (clear-stream _test-error-stream)
 6065     (clear-stream $_test-error-buffered-file->buffer)
 6066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6067     68/push 0/imm32
 6068     68/push 0/imm32
 6069     89/<- %edx 4/r32/esp
 6070     (tailor-exit-descriptor %edx 0x10)
 6071     #
 6072     (write _test-input-stream "type t {\n")
 6073     (write _test-input-stream "  a: (addr int)\n")
 6074     (write _test-input-stream "}\n")
 6075     # convert
 6076     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6077     # registers except esp clobbered at this point
 6078     # restore ed
 6079     89/<- %edx 4/r32/esp
 6080     (flush _test-output-buffered-file)
 6081     (flush _test-error-buffered-file)
 6082 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6088     # check output
 6089     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6090     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6091     # check that stop(1) was called
 6092     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6093     # don't restore from ebp
 6094     81 0/subop/add %esp 8/imm32
 6095     # . epilogue
 6096     5d/pop-to-ebp
 6097     c3/return
 6098 
 6099 test-convert-function-with-local-var-with-user-defined-type:
 6100     # . prologue
 6101     55/push-ebp
 6102     89/<- %ebp 4/r32/esp
 6103     # setup
 6104     (clear-stream _test-input-stream)
 6105     (clear-stream $_test-input-buffered-file->buffer)
 6106     (clear-stream _test-output-stream)
 6107     (clear-stream $_test-output-buffered-file->buffer)
 6108     #
 6109     (write _test-input-stream "fn foo {\n")
 6110     (write _test-input-stream "  var a: t\n")
 6111     (write _test-input-stream "}\n")
 6112     (write _test-input-stream "type t {\n")
 6113     (write _test-input-stream "  x: int\n")
 6114     (write _test-input-stream "  y: int\n")
 6115     (write _test-input-stream "}\n")
 6116     # convert
 6117     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6118     (flush _test-output-buffered-file)
 6119 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6125     # check output
 6126     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 6127     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 6128     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 6129     (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")
 6130     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 6131     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 6132     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 6133     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 6134     (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")
 6135     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 6136     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 6137     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 6138     (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")
 6139     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 6140     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 6141     # . epilogue
 6142     89/<- %esp 5/r32/ebp
 6143     5d/pop-to-ebp
 6144     c3/return
 6145 
 6146 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 6147     # . prologue
 6148     55/push-ebp
 6149     89/<- %ebp 4/r32/esp
 6150     # setup
 6151     (clear-stream _test-input-stream)
 6152     (clear-stream $_test-input-buffered-file->buffer)
 6153     (clear-stream _test-output-stream)
 6154     (clear-stream $_test-output-buffered-file->buffer)
 6155     #
 6156     (write _test-input-stream "fn foo {\n")
 6157     (write _test-input-stream "  var a: t\n")
 6158     (write _test-input-stream "}\n")
 6159     (write _test-input-stream "type t {\n")
 6160     (write _test-input-stream "  x: s\n")
 6161     (write _test-input-stream "}\n")
 6162     (write _test-input-stream "type s {\n")
 6163     (write _test-input-stream "  z: int\n")
 6164     (write _test-input-stream "}\n")
 6165     # convert
 6166     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6167     (flush _test-output-buffered-file)
 6168 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6174     # check output
 6175     (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")
 6176     (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")
 6177     (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")
 6178     (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")
 6179     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 6180     (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")
 6181     (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")
 6182     (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")
 6183     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 6184     (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")
 6185     (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")
 6186     (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")
 6187     (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")
 6188     (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")
 6189     # . epilogue
 6190     89/<- %esp 5/r32/ebp
 6191     5d/pop-to-ebp
 6192     c3/return
 6193 
 6194 test-convert-function-call-with-arg-of-user-defined-type:
 6195     # . prologue
 6196     55/push-ebp
 6197     89/<- %ebp 4/r32/esp
 6198     # setup
 6199     (clear-stream _test-input-stream)
 6200     (clear-stream $_test-input-buffered-file->buffer)
 6201     (clear-stream _test-output-stream)
 6202     (clear-stream $_test-output-buffered-file->buffer)
 6203     #
 6204     (write _test-input-stream "fn f {\n")
 6205     (write _test-input-stream "  var a: t\n")
 6206     (write _test-input-stream "  foo a\n")
 6207     (write _test-input-stream "}\n")
 6208     (write _test-input-stream "fn foo x: t {\n")
 6209     (write _test-input-stream "}\n")
 6210     (write _test-input-stream "type t {\n")
 6211     (write _test-input-stream "  x: int\n")
 6212     (write _test-input-stream "  y: int\n")
 6213     (write _test-input-stream "}\n")
 6214     # convert
 6215     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6216     (flush _test-output-buffered-file)
 6217 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6223     # check output
 6224     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6225     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6226     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6227     (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")
 6228     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6229     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6230     # var a: t
 6231     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6232     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6233     # foo a
 6234     (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")
 6235     #
 6236     (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")
 6237     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6238     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6239     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6240     (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")
 6241     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6242     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6243     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6244     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6245     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6246     (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")
 6247     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6248     (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")
 6249     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6250     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6251     # . epilogue
 6252     89/<- %esp 5/r32/ebp
 6253     5d/pop-to-ebp
 6254     c3/return
 6255 
 6256 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 6257     # . prologue
 6258     55/push-ebp
 6259     89/<- %ebp 4/r32/esp
 6260     # setup
 6261     (clear-stream _test-input-stream)
 6262     (clear-stream $_test-input-buffered-file->buffer)
 6263     (clear-stream _test-output-stream)
 6264     (clear-stream $_test-output-buffered-file->buffer)
 6265     #
 6266     (write _test-input-stream "fn f {\n")
 6267     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 6268     (write _test-input-stream "  foo *a\n")
 6269     (write _test-input-stream "}\n")
 6270     (write _test-input-stream "fn foo x: t {\n")
 6271     (write _test-input-stream "}\n")
 6272     (write _test-input-stream "type t {\n")
 6273     (write _test-input-stream "  x: int\n")
 6274     (write _test-input-stream "  y: int\n")
 6275     (write _test-input-stream "}\n")
 6276     # convert
 6277     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6278     (flush _test-output-buffered-file)
 6279 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6285     # check output
 6286     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6287     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6288     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6289     (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")
 6290     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6291     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6292     # var a
 6293     (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")
 6294     (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")
 6295     # foo a
 6296     (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")
 6297     #
 6298     (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")
 6299     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6300     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6301     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6302     (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")
 6303     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6304     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6305     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6306     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6307     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6308     (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")
 6309     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6310     (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")
 6311     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6312     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6313     # . epilogue
 6314     89/<- %esp 5/r32/ebp
 6315     5d/pop-to-ebp
 6316     c3/return
 6317 
 6318 # we don't have special support for call-by-reference; just explicitly create
 6319 # a new variable with the address of the arg
 6320 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 6321     # . prologue
 6322     55/push-ebp
 6323     89/<- %ebp 4/r32/esp
 6324     # setup
 6325     (clear-stream _test-input-stream)
 6326     (clear-stream $_test-input-buffered-file->buffer)
 6327     (clear-stream _test-output-stream)
 6328     (clear-stream $_test-output-buffered-file->buffer)
 6329     #
 6330     (write _test-input-stream "fn f {\n")
 6331     (write _test-input-stream "  var a: t\n")
 6332     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 6333     (write _test-input-stream "  foo b\n")
 6334     (write _test-input-stream "}\n")
 6335     (write _test-input-stream "fn foo x: (addr t) {\n")
 6336     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 6337     (write _test-input-stream "}\n")
 6338     (write _test-input-stream "type t {\n")
 6339     (write _test-input-stream "  x: int\n")
 6340     (write _test-input-stream "  y: int\n")
 6341     (write _test-input-stream "}\n")
 6342     # convert
 6343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6344     (flush _test-output-buffered-file)
 6345 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6351     # check output
 6352     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 6353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 6354     (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")
 6355     (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")
 6356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 6357     (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")
 6358     # var a: t
 6359     (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")
 6360     (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")
 6361     # var b/eax: (addr t)
 6362     (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")
 6363     (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")
 6364     # foo a
 6365     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 6366     #
 6367     (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")
 6368     (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")
 6369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 6370     (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")
 6371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 6372     (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")
 6373     (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")
 6374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 6375     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 6376     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 6377     (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")
 6378     (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")
 6379     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 6380     (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")
 6381     (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")
 6382     (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")
 6383     (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")
 6384     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 6385     (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")
 6386     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 6387     (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")
 6388     (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")
 6389     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 6390     # . epilogue
 6391     89/<- %esp 5/r32/ebp
 6392     5d/pop-to-ebp
 6393     c3/return
 6394 
 6395 test-convert-get-on-local-variable:
 6396     # . prologue
 6397     55/push-ebp
 6398     89/<- %ebp 4/r32/esp
 6399     # setup
 6400     (clear-stream _test-input-stream)
 6401     (clear-stream $_test-input-buffered-file->buffer)
 6402     (clear-stream _test-output-stream)
 6403     (clear-stream $_test-output-buffered-file->buffer)
 6404     #
 6405     (write _test-input-stream "fn foo {\n")
 6406     (write _test-input-stream "  var a: t\n")
 6407     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6408     (write _test-input-stream "}\n")
 6409     (write _test-input-stream "type t {\n")
 6410     (write _test-input-stream "  x: int\n")
 6411     (write _test-input-stream "  y: int\n")
 6412     (write _test-input-stream "}\n")
 6413     # convert
 6414     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6415     (flush _test-output-buffered-file)
 6416 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6422     # check output
 6423     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 6424     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 6425     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 6426     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 6427     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 6428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 6429     # var a
 6430     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 6431     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 6432     # var c
 6433     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 6434     # get
 6435     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 6436     # reclaim c
 6437     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 6438     # reclaim a
 6439     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 6440     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 6441     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 6442     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 6443     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 6444     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 6445     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 6446     # . epilogue
 6447     89/<- %esp 5/r32/ebp
 6448     5d/pop-to-ebp
 6449     c3/return
 6450 
 6451 test-convert-get-on-function-argument:
 6452     # . prologue
 6453     55/push-ebp
 6454     89/<- %ebp 4/r32/esp
 6455     # setup
 6456     (clear-stream _test-input-stream)
 6457     (clear-stream $_test-input-buffered-file->buffer)
 6458     (clear-stream _test-output-stream)
 6459     (clear-stream $_test-output-buffered-file->buffer)
 6460     #
 6461     (write _test-input-stream "fn foo a: t {\n")
 6462     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6463     (write _test-input-stream "}\n")
 6464     (write _test-input-stream "type t {\n")
 6465     (write _test-input-stream "  x: int\n")
 6466     (write _test-input-stream "  y: int\n")
 6467     (write _test-input-stream "}\n")
 6468     # convert
 6469     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6470     (flush _test-output-buffered-file)
 6471 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6477     # check output
 6478     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 6479     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 6480     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 6481     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 6482     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 6483     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 6484     # var c
 6485     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 6486     # get
 6487     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 6488     # reclaim c
 6489     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 6490     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 6491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 6492     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 6493     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 6494     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 6495     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 6496     # . epilogue
 6497     89/<- %esp 5/r32/ebp
 6498     5d/pop-to-ebp
 6499     c3/return
 6500 
 6501 test-convert-get-on-function-argument-with-known-type:
 6502     # . prologue
 6503     55/push-ebp
 6504     89/<- %ebp 4/r32/esp
 6505     # setup
 6506     (clear-stream _test-input-stream)
 6507     (clear-stream $_test-input-buffered-file->buffer)
 6508     (clear-stream _test-output-stream)
 6509     (clear-stream $_test-output-buffered-file->buffer)
 6510     #
 6511     (write _test-input-stream "type t {\n")
 6512     (write _test-input-stream "  x: int\n")
 6513     (write _test-input-stream "  y: int\n")
 6514     (write _test-input-stream "}\n")
 6515     (write _test-input-stream "fn foo a: t {\n")
 6516     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6517     (write _test-input-stream "}\n")
 6518     # convert
 6519     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6520     (flush _test-output-buffered-file)
 6521 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6527     # check output
 6528     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 6529     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 6530     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 6531     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 6532     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 6533     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 6534     # var c
 6535     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 6536     # get
 6537     (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")
 6538     # reclaim c
 6539     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 6540     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 6541     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 6542     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 6543     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 6544     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 6545     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 6546     # . epilogue
 6547     89/<- %esp 5/r32/ebp
 6548     5d/pop-to-ebp
 6549     c3/return
 6550 
 6551 test-add-with-too-many-inouts:
 6552     # . prologue
 6553     55/push-ebp
 6554     89/<- %ebp 4/r32/esp
 6555     # setup
 6556     (clear-stream _test-input-stream)
 6557     (clear-stream $_test-input-buffered-file->buffer)
 6558     (clear-stream _test-output-stream)
 6559     (clear-stream $_test-output-buffered-file->buffer)
 6560     (clear-stream _test-error-stream)
 6561     (clear-stream $_test-error-buffered-file->buffer)
 6562     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6563     68/push 0/imm32
 6564     68/push 0/imm32
 6565     89/<- %edx 4/r32/esp
 6566     (tailor-exit-descriptor %edx 0x10)
 6567     #
 6568     (write _test-input-stream "fn foo {\n")
 6569     (write _test-input-stream "  var a: int\n")
 6570     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 6571     (write _test-input-stream "}\n")
 6572     # convert
 6573     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6574     # registers except esp clobbered at this point
 6575     # restore ed
 6576     89/<- %edx 4/r32/esp
 6577     (flush _test-output-buffered-file)
 6578     (flush _test-error-buffered-file)
 6579 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6585     # check output
 6586     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 6587     (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")
 6588     # check that stop(1) was called
 6589     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 6590     # don't restore from ebp
 6591     81 0/subop/add %esp 8/imm32
 6592     # . epilogue
 6593     5d/pop-to-ebp
 6594     c3/return
 6595 
 6596 test-add-with-too-many-inouts-2:
 6597     # . prologue
 6598     55/push-ebp
 6599     89/<- %ebp 4/r32/esp
 6600     # setup
 6601     (clear-stream _test-input-stream)
 6602     (clear-stream $_test-input-buffered-file->buffer)
 6603     (clear-stream _test-output-stream)
 6604     (clear-stream $_test-output-buffered-file->buffer)
 6605     (clear-stream _test-error-stream)
 6606     (clear-stream $_test-error-buffered-file->buffer)
 6607     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6608     68/push 0/imm32
 6609     68/push 0/imm32
 6610     89/<- %edx 4/r32/esp
 6611     (tailor-exit-descriptor %edx 0x10)
 6612     #
 6613     (write _test-input-stream "fn foo {\n")
 6614     (write _test-input-stream "  var a: int\n")
 6615     (write _test-input-stream "  add-to a, 0, 1\n")
 6616     (write _test-input-stream "}\n")
 6617     # convert
 6618     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6619     # registers except esp clobbered at this point
 6620     # restore ed
 6621     89/<- %edx 4/r32/esp
 6622     (flush _test-output-buffered-file)
 6623     (flush _test-error-buffered-file)
 6624 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6630     # check output
 6631     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 6632     (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")
 6633     # check that stop(1) was called
 6634     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 6635     # don't restore from ebp
 6636     81 0/subop/add %esp 8/imm32
 6637     # . epilogue
 6638     5d/pop-to-ebp
 6639     c3/return
 6640 
 6641 test-add-with-too-many-outputs:
 6642     # . prologue
 6643     55/push-ebp
 6644     89/<- %ebp 4/r32/esp
 6645     # setup
 6646     (clear-stream _test-input-stream)
 6647     (clear-stream $_test-input-buffered-file->buffer)
 6648     (clear-stream _test-output-stream)
 6649     (clear-stream $_test-output-buffered-file->buffer)
 6650     (clear-stream _test-error-stream)
 6651     (clear-stream $_test-error-buffered-file->buffer)
 6652     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6653     68/push 0/imm32
 6654     68/push 0/imm32
 6655     89/<- %edx 4/r32/esp
 6656     (tailor-exit-descriptor %edx 0x10)
 6657     #
 6658     (write _test-input-stream "fn foo {\n")
 6659     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 6660     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 6661     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 6662     (write _test-input-stream "  c, b <- add a\n")
 6663     (write _test-input-stream "}\n")
 6664     # convert
 6665     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6666     # registers except esp clobbered at this point
 6667     # restore ed
 6668     89/<- %edx 4/r32/esp
 6669     (flush _test-output-buffered-file)
 6670     (flush _test-error-buffered-file)
 6671 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6677     # check output
 6678     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 6679     (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")
 6680     # check that stop(1) was called
 6681     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 6682     # don't restore from ebp
 6683     81 0/subop/add %esp 8/imm32
 6684     # . epilogue
 6685     5d/pop-to-ebp
 6686     c3/return
 6687 
 6688 test-add-with-non-number:
 6689     # . prologue
 6690     55/push-ebp
 6691     89/<- %ebp 4/r32/esp
 6692     # setup
 6693     (clear-stream _test-input-stream)
 6694     (clear-stream $_test-input-buffered-file->buffer)
 6695     (clear-stream _test-output-stream)
 6696     (clear-stream $_test-output-buffered-file->buffer)
 6697     (clear-stream _test-error-stream)
 6698     (clear-stream $_test-error-buffered-file->buffer)
 6699     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6700     68/push 0/imm32
 6701     68/push 0/imm32
 6702     89/<- %edx 4/r32/esp
 6703     (tailor-exit-descriptor %edx 0x10)
 6704     #
 6705     (write _test-input-stream "fn foo {\n")
 6706     (write _test-input-stream "  var a: int\n")
 6707     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 6708     (write _test-input-stream "}\n")
 6709     # convert
 6710     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6711     # registers except esp clobbered at this point
 6712     # restore ed
 6713     89/<- %edx 4/r32/esp
 6714     (flush _test-output-buffered-file)
 6715     (flush _test-error-buffered-file)
 6716 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6722     # check output
 6723     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 6724     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: 'b' must be a non-addr non-offset scalar"  "F - test-add-with-non-number: error message")
 6725     # check that stop(1) was called
 6726     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 6727     # don't restore from ebp
 6728     81 0/subop/add %esp 8/imm32
 6729     # . epilogue
 6730     5d/pop-to-ebp
 6731     c3/return
 6732 
 6733 test-add-with-addr-dereferenced:
 6734     # . prologue
 6735     55/push-ebp
 6736     89/<- %ebp 4/r32/esp
 6737     # setup
 6738     (clear-stream _test-input-stream)
 6739     (clear-stream $_test-input-buffered-file->buffer)
 6740     (clear-stream _test-output-stream)
 6741     (clear-stream $_test-output-buffered-file->buffer)
 6742     #
 6743     (write _test-input-stream "fn foo {\n")
 6744     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 6745     (write _test-input-stream "  add-to *a, 1\n")
 6746     (write _test-input-stream "}\n")
 6747     # convert
 6748     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6749     (flush _test-output-buffered-file)
 6750     # no error
 6751     # . epilogue
 6752     89/<- %esp 5/r32/ebp
 6753     5d/pop-to-ebp
 6754     c3/return
 6755 
 6756 test-copy-with-no-inout:
 6757     # . prologue
 6758     55/push-ebp
 6759     89/<- %ebp 4/r32/esp
 6760     # setup
 6761     (clear-stream _test-input-stream)
 6762     (clear-stream $_test-input-buffered-file->buffer)
 6763     (clear-stream _test-output-stream)
 6764     (clear-stream $_test-output-buffered-file->buffer)
 6765     (clear-stream _test-error-stream)
 6766     (clear-stream $_test-error-buffered-file->buffer)
 6767     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6768     68/push 0/imm32
 6769     68/push 0/imm32
 6770     89/<- %edx 4/r32/esp
 6771     (tailor-exit-descriptor %edx 0x10)
 6772     #
 6773     (write _test-input-stream "fn foo {\n")
 6774     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 6775     (write _test-input-stream "}\n")
 6776     # convert
 6777     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6778     # registers except esp clobbered at this point
 6779     # restore ed
 6780     89/<- %edx 4/r32/esp
 6781     (flush _test-output-buffered-file)
 6782     (flush _test-error-buffered-file)
 6783 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6789     # check output
 6790     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 6791     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 6792     # check that stop(1) was called
 6793     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 6794     # don't restore from ebp
 6795     81 0/subop/add %esp 8/imm32
 6796     # . epilogue
 6797     5d/pop-to-ebp
 6798     c3/return
 6799 
 6800 test-copy-with-multiple-inouts:
 6801     # . prologue
 6802     55/push-ebp
 6803     89/<- %ebp 4/r32/esp
 6804     # setup
 6805     (clear-stream _test-input-stream)
 6806     (clear-stream $_test-input-buffered-file->buffer)
 6807     (clear-stream _test-output-stream)
 6808     (clear-stream $_test-output-buffered-file->buffer)
 6809     (clear-stream _test-error-stream)
 6810     (clear-stream $_test-error-buffered-file->buffer)
 6811     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6812     68/push 0/imm32
 6813     68/push 0/imm32
 6814     89/<- %edx 4/r32/esp
 6815     (tailor-exit-descriptor %edx 0x10)
 6816     #
 6817     (write _test-input-stream "fn foo {\n")
 6818     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 6819     (write _test-input-stream "}\n")
 6820     # convert
 6821     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6822     # registers except esp clobbered at this point
 6823     # restore ed
 6824     89/<- %edx 4/r32/esp
 6825     (flush _test-output-buffered-file)
 6826     (flush _test-error-buffered-file)
 6827 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6833     # check output
 6834     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 6835     (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")
 6836     # check that stop(1) was called
 6837     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 6838     # don't restore from ebp
 6839     81 0/subop/add %esp 8/imm32
 6840     # . epilogue
 6841     5d/pop-to-ebp
 6842     c3/return
 6843 
 6844 test-copy-with-no-output:
 6845     # . prologue
 6846     55/push-ebp
 6847     89/<- %ebp 4/r32/esp
 6848     # setup
 6849     (clear-stream _test-input-stream)
 6850     (clear-stream $_test-input-buffered-file->buffer)
 6851     (clear-stream _test-output-stream)
 6852     (clear-stream $_test-output-buffered-file->buffer)
 6853     (clear-stream _test-error-stream)
 6854     (clear-stream $_test-error-buffered-file->buffer)
 6855     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6856     68/push 0/imm32
 6857     68/push 0/imm32
 6858     89/<- %edx 4/r32/esp
 6859     (tailor-exit-descriptor %edx 0x10)
 6860     #
 6861     (write _test-input-stream "fn foo {\n")
 6862     (write _test-input-stream "  copy 0\n")
 6863     (write _test-input-stream "}\n")
 6864     # convert
 6865     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6866     # registers except esp clobbered at this point
 6867     # restore ed
 6868     89/<- %edx 4/r32/esp
 6869     (flush _test-output-buffered-file)
 6870     (flush _test-error-buffered-file)
 6871 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6877     # check output
 6878     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 6879     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 6880     # check that stop(1) was called
 6881     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 6882     # don't restore from ebp
 6883     81 0/subop/add %esp 8/imm32
 6884     # . epilogue
 6885     5d/pop-to-ebp
 6886     c3/return
 6887 
 6888 test-copy-with-multiple-outputs:
 6889     # . prologue
 6890     55/push-ebp
 6891     89/<- %ebp 4/r32/esp
 6892     # setup
 6893     (clear-stream _test-input-stream)
 6894     (clear-stream $_test-input-buffered-file->buffer)
 6895     (clear-stream _test-output-stream)
 6896     (clear-stream $_test-output-buffered-file->buffer)
 6897     (clear-stream _test-error-stream)
 6898     (clear-stream $_test-error-buffered-file->buffer)
 6899     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6900     68/push 0/imm32
 6901     68/push 0/imm32
 6902     89/<- %edx 4/r32/esp
 6903     (tailor-exit-descriptor %edx 0x10)
 6904     #
 6905     (write _test-input-stream "fn foo {\n")
 6906     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 6907     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 6908     (write _test-input-stream "  x, y <- copy 0\n")
 6909     (write _test-input-stream "}\n")
 6910     # convert
 6911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6912     # registers except esp clobbered at this point
 6913     # restore ed
 6914     89/<- %edx 4/r32/esp
 6915     (flush _test-output-buffered-file)
 6916     (flush _test-error-buffered-file)
 6917 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6923     # check output
 6924     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 6925     (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")
 6926     # check that stop(1) was called
 6927     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 6928     # don't restore from ebp
 6929     81 0/subop/add %esp 8/imm32
 6930     # . epilogue
 6931     5d/pop-to-ebp
 6932     c3/return
 6933 
 6934 test-copy-invalid-value-to-address:
 6935     # . prologue
 6936     55/push-ebp
 6937     89/<- %ebp 4/r32/esp
 6938     # setup
 6939     (clear-stream _test-input-stream)
 6940     (clear-stream $_test-input-buffered-file->buffer)
 6941     (clear-stream _test-output-stream)
 6942     (clear-stream $_test-output-buffered-file->buffer)
 6943     (clear-stream _test-error-stream)
 6944     (clear-stream $_test-error-buffered-file->buffer)
 6945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6946     68/push 0/imm32
 6947     68/push 0/imm32
 6948     89/<- %edx 4/r32/esp
 6949     (tailor-exit-descriptor %edx 0x10)
 6950     #
 6951     (write _test-input-stream "fn foo {\n")
 6952     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 6953     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 6954     (write _test-input-stream "}\n")
 6955     # convert
 6956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6957     # registers except esp clobbered at this point
 6958     # restore ed
 6959     89/<- %edx 4/r32/esp
 6960     (flush _test-output-buffered-file)
 6961     (flush _test-error-buffered-file)
 6962 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6968     # check output
 6969     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 6970     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 6971     # check that stop(1) was called
 6972     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 6973     # don't restore from ebp
 6974     81 0/subop/add %esp 8/imm32
 6975     # . epilogue
 6976     5d/pop-to-ebp
 6977     c3/return
 6978 
 6979 test-copy-null-value-to-addr:
 6980     # . prologue
 6981     55/push-ebp
 6982     89/<- %ebp 4/r32/esp
 6983     # setup
 6984     (clear-stream _test-input-stream)
 6985     (clear-stream $_test-input-buffered-file->buffer)
 6986     (clear-stream _test-output-stream)
 6987     (clear-stream $_test-output-buffered-file->buffer)
 6988     #
 6989     (write _test-input-stream "fn foo {\n")
 6990     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 6991     (write _test-input-stream "}\n")
 6992     # convert
 6993     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6994     (flush _test-output-buffered-file)
 6995 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7001     # no errors
 7002     # . epilogue
 7003     89/<- %esp 5/r32/ebp
 7004     5d/pop-to-ebp
 7005     c3/return
 7006 
 7007 test-copy-invalid-value-to-offset:
 7008     # . prologue
 7009     55/push-ebp
 7010     89/<- %ebp 4/r32/esp
 7011     # setup
 7012     (clear-stream _test-input-stream)
 7013     (clear-stream $_test-input-buffered-file->buffer)
 7014     (clear-stream _test-output-stream)
 7015     (clear-stream $_test-output-buffered-file->buffer)
 7016     (clear-stream _test-error-stream)
 7017     (clear-stream $_test-error-buffered-file->buffer)
 7018     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7019     68/push 0/imm32
 7020     68/push 0/imm32
 7021     89/<- %edx 4/r32/esp
 7022     (tailor-exit-descriptor %edx 0x10)
 7023     #
 7024     (write _test-input-stream "fn foo {\n")
 7025     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7026     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7027     (write _test-input-stream "}\n")
 7028     # convert
 7029     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7030     # registers except esp clobbered at this point
 7031     # restore ed
 7032     89/<- %edx 4/r32/esp
 7033     (flush _test-output-buffered-file)
 7034     (flush _test-error-buffered-file)
 7035 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7041     # check output
 7042     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7043     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7044     # check that stop(1) was called
 7045     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7046     # don't restore from ebp
 7047     81 0/subop/add %esp 8/imm32
 7048     # . epilogue
 7049     5d/pop-to-ebp
 7050     c3/return
 7051 
 7052 test-copy-null-value-to-offset:
 7053     # . prologue
 7054     55/push-ebp
 7055     89/<- %ebp 4/r32/esp
 7056     # setup
 7057     (clear-stream _test-input-stream)
 7058     (clear-stream $_test-input-buffered-file->buffer)
 7059     (clear-stream _test-output-stream)
 7060     (clear-stream $_test-output-buffered-file->buffer)
 7061     #
 7062     (write _test-input-stream "fn foo {\n")
 7063     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7064     (write _test-input-stream "}\n")
 7065     # convert
 7066     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7067     (flush _test-output-buffered-file)
 7068 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7074     # no errors
 7075     # . epilogue
 7076     89/<- %esp 5/r32/ebp
 7077     5d/pop-to-ebp
 7078     c3/return
 7079 
 7080 test-copy-deref-address:
 7081     # . prologue
 7082     55/push-ebp
 7083     89/<- %ebp 4/r32/esp
 7084     # setup
 7085     (clear-stream _test-input-stream)
 7086     (clear-stream $_test-input-buffered-file->buffer)
 7087     (clear-stream _test-output-stream)
 7088     (clear-stream $_test-output-buffered-file->buffer)
 7089     #
 7090     (write _test-input-stream "fn foo {\n")
 7091     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 7092     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 7093     (write _test-input-stream "}\n")
 7094     # convert
 7095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7096     (flush _test-output-buffered-file)
 7097 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7103     # not bothering checking output
 7104     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-deref-address: error message")
 7105     # . epilogue
 7106     5d/pop-to-ebp
 7107     c3/return
 7108 
 7109 test-copy-to-non-register:
 7110     # . prologue
 7111     55/push-ebp
 7112     89/<- %ebp 4/r32/esp
 7113     # setup
 7114     (clear-stream _test-input-stream)
 7115     (clear-stream $_test-input-buffered-file->buffer)
 7116     (clear-stream _test-output-stream)
 7117     (clear-stream $_test-output-buffered-file->buffer)
 7118     (clear-stream _test-error-stream)
 7119     (clear-stream $_test-error-buffered-file->buffer)
 7120     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7121     68/push 0/imm32
 7122     68/push 0/imm32
 7123     89/<- %edx 4/r32/esp
 7124     (tailor-exit-descriptor %edx 0x10)
 7125     #
 7126     (write _test-input-stream "fn foo {\n")
 7127     (write _test-input-stream "  var x: int\n")
 7128     (write _test-input-stream "  x <- copy 0\n")
 7129     (write _test-input-stream "}\n")
 7130     # convert
 7131     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7132     # registers except esp clobbered at this point
 7133     # restore ed
 7134     89/<- %edx 4/r32/esp
 7135     (flush _test-output-buffered-file)
 7136     (flush _test-error-buffered-file)
 7137 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7143     # check output
 7144     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 7145     (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")
 7146     # check that stop(1) was called
 7147     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 7148     # don't restore from ebp
 7149     81 0/subop/add %esp 8/imm32
 7150     # . epilogue
 7151     5d/pop-to-ebp
 7152     c3/return
 7153 
 7154 test-copy-non-scalar:
 7155     # . prologue
 7156     55/push-ebp
 7157     89/<- %ebp 4/r32/esp
 7158     # setup
 7159     (clear-stream _test-input-stream)
 7160     (clear-stream $_test-input-buffered-file->buffer)
 7161     (clear-stream _test-output-stream)
 7162     (clear-stream $_test-output-buffered-file->buffer)
 7163     (clear-stream _test-error-stream)
 7164     (clear-stream $_test-error-buffered-file->buffer)
 7165     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7166     68/push 0/imm32
 7167     68/push 0/imm32
 7168     89/<- %edx 4/r32/esp
 7169     (tailor-exit-descriptor %edx 0x10)
 7170     #
 7171     (write _test-input-stream "fn foo {\n")
 7172     (write _test-input-stream "  var x: (handle int)\n")
 7173     (write _test-input-stream "  var y/eax: int <- copy x\n")
 7174     (write _test-input-stream "}\n")
 7175     # convert
 7176     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7177     # registers except esp clobbered at this point
 7178     # restore ed
 7179     89/<- %edx 4/r32/esp
 7180     (flush _test-output-buffered-file)
 7181     (flush _test-error-buffered-file)
 7182 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7188     # check output
 7189     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-scalar: output should be empty")
 7190     (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")
 7191     # check that stop(1) was called
 7192     (check-ints-equal *(edx+4) 2 "F - test-copy-non-scalar: exit status")
 7193     # don't restore from ebp
 7194     81 0/subop/add %esp 8/imm32
 7195     # . epilogue
 7196     5d/pop-to-ebp
 7197     c3/return
 7198 
 7199 test-copy-to-with-no-inout:
 7200     # . prologue
 7201     55/push-ebp
 7202     89/<- %ebp 4/r32/esp
 7203     # setup
 7204     (clear-stream _test-input-stream)
 7205     (clear-stream $_test-input-buffered-file->buffer)
 7206     (clear-stream _test-output-stream)
 7207     (clear-stream $_test-output-buffered-file->buffer)
 7208     (clear-stream _test-error-stream)
 7209     (clear-stream $_test-error-buffered-file->buffer)
 7210     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7211     68/push 0/imm32
 7212     68/push 0/imm32
 7213     89/<- %edx 4/r32/esp
 7214     (tailor-exit-descriptor %edx 0x10)
 7215     #
 7216     (write _test-input-stream "fn foo {\n")
 7217     (write _test-input-stream "  copy-to\n")
 7218     (write _test-input-stream "}\n")
 7219     # convert
 7220     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7221     # registers except esp clobbered at this point
 7222     # restore ed
 7223     89/<- %edx 4/r32/esp
 7224     (flush _test-output-buffered-file)
 7225     (flush _test-error-buffered-file)
 7226 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7232     # check output
 7233     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 7234     (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")
 7235     # check that stop(1) was called
 7236     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 7237     # don't restore from ebp
 7238     81 0/subop/add %esp 8/imm32
 7239     # . epilogue
 7240     5d/pop-to-ebp
 7241     c3/return
 7242 
 7243 test-copy-to-with-no-input:
 7244     # . prologue
 7245     55/push-ebp
 7246     89/<- %ebp 4/r32/esp
 7247     # setup
 7248     (clear-stream _test-input-stream)
 7249     (clear-stream $_test-input-buffered-file->buffer)
 7250     (clear-stream _test-output-stream)
 7251     (clear-stream $_test-output-buffered-file->buffer)
 7252     (clear-stream _test-error-stream)
 7253     (clear-stream $_test-error-buffered-file->buffer)
 7254     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7255     68/push 0/imm32
 7256     68/push 0/imm32
 7257     89/<- %edx 4/r32/esp
 7258     (tailor-exit-descriptor %edx 0x10)
 7259     #
 7260     (write _test-input-stream "fn foo {\n")
 7261     (write _test-input-stream "  var x: boolean\n")
 7262     (write _test-input-stream "  copy-to x\n")
 7263     (write _test-input-stream "}\n")
 7264     # convert
 7265     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7266     # registers except esp clobbered at this point
 7267     # restore ed
 7268     89/<- %edx 4/r32/esp
 7269     (flush _test-output-buffered-file)
 7270     (flush _test-error-buffered-file)
 7271 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7277     # check output
 7278     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-input: output should be empty")
 7279     (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")
 7280     # check that stop(1) was called
 7281     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-input: exit status")
 7282     # don't restore from ebp
 7283     81 0/subop/add %esp 8/imm32
 7284     # . epilogue
 7285     5d/pop-to-ebp
 7286     c3/return
 7287 
 7288 test-copy-to-with-no-register:
 7289     # . prologue
 7290     55/push-ebp
 7291     89/<- %ebp 4/r32/esp
 7292     # setup
 7293     (clear-stream _test-input-stream)
 7294     (clear-stream $_test-input-buffered-file->buffer)
 7295     (clear-stream _test-output-stream)
 7296     (clear-stream $_test-output-buffered-file->buffer)
 7297     (clear-stream _test-error-stream)
 7298     (clear-stream $_test-error-buffered-file->buffer)
 7299     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7300     68/push 0/imm32
 7301     68/push 0/imm32
 7302     89/<- %edx 4/r32/esp
 7303     (tailor-exit-descriptor %edx 0x10)
 7304     #
 7305     (write _test-input-stream "fn foo {\n")
 7306     (write _test-input-stream "  var x: boolean\n")
 7307     (write _test-input-stream "  copy-to x, x\n")
 7308     (write _test-input-stream "}\n")
 7309     # convert
 7310     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7311     # registers except esp clobbered at this point
 7312     # restore ed
 7313     89/<- %edx 4/r32/esp
 7314     (flush _test-output-buffered-file)
 7315     (flush _test-error-buffered-file)
 7316 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7322     # check output
 7323     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 7324     (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")
 7325     # check that stop(1) was called
 7326     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 7327     # don't restore from ebp
 7328     81 0/subop/add %esp 8/imm32
 7329     # . epilogue
 7330     5d/pop-to-ebp
 7331     c3/return
 7332 
 7333 test-copy-to-with-too-many-inouts:
 7334     # . prologue
 7335     55/push-ebp
 7336     89/<- %ebp 4/r32/esp
 7337     # setup
 7338     (clear-stream _test-input-stream)
 7339     (clear-stream $_test-input-buffered-file->buffer)
 7340     (clear-stream _test-output-stream)
 7341     (clear-stream $_test-output-buffered-file->buffer)
 7342     (clear-stream _test-error-stream)
 7343     (clear-stream $_test-error-buffered-file->buffer)
 7344     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7345     68/push 0/imm32
 7346     68/push 0/imm32
 7347     89/<- %edx 4/r32/esp
 7348     (tailor-exit-descriptor %edx 0x10)
 7349     #
 7350     (write _test-input-stream "fn foo {\n")
 7351     (write _test-input-stream "  var x: boolean\n")
 7352     (write _test-input-stream "  copy-to x, 0, 0\n")
 7353     (write _test-input-stream "}\n")
 7354     # convert
 7355     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7356     # registers except esp clobbered at this point
 7357     # restore ed
 7358     89/<- %edx 4/r32/esp
 7359     (flush _test-output-buffered-file)
 7360     (flush _test-error-buffered-file)
 7361 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7367     # check output
 7368     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 7369     (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")
 7370     # check that stop(1) was called
 7371     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 7372     # don't restore from ebp
 7373     81 0/subop/add %esp 8/imm32
 7374     # . epilogue
 7375     5d/pop-to-ebp
 7376     c3/return
 7377 
 7378 test-copy-to-with-output:
 7379     # . prologue
 7380     55/push-ebp
 7381     89/<- %ebp 4/r32/esp
 7382     # setup
 7383     (clear-stream _test-input-stream)
 7384     (clear-stream $_test-input-buffered-file->buffer)
 7385     (clear-stream _test-output-stream)
 7386     (clear-stream $_test-output-buffered-file->buffer)
 7387     (clear-stream _test-error-stream)
 7388     (clear-stream $_test-error-buffered-file->buffer)
 7389     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7390     68/push 0/imm32
 7391     68/push 0/imm32
 7392     89/<- %edx 4/r32/esp
 7393     (tailor-exit-descriptor %edx 0x10)
 7394     #
 7395     (write _test-input-stream "fn foo {\n")
 7396     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7397     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7398     (write _test-input-stream "  x <- copy-to y, 0\n")
 7399     (write _test-input-stream "}\n")
 7400     # convert
 7401     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7402     # registers except esp clobbered at this point
 7403     # restore ed
 7404     89/<- %edx 4/r32/esp
 7405     (flush _test-output-buffered-file)
 7406     (flush _test-error-buffered-file)
 7407 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7413     # check output
 7414     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 7415     (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")
 7416     # check that stop(1) was called
 7417     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 7418     # don't restore from ebp
 7419     81 0/subop/add %esp 8/imm32
 7420     # . epilogue
 7421     5d/pop-to-ebp
 7422     c3/return
 7423 
 7424 test-copy-to-invalid-value-to-address:
 7425     # . prologue
 7426     55/push-ebp
 7427     89/<- %ebp 4/r32/esp
 7428     # setup
 7429     (clear-stream _test-input-stream)
 7430     (clear-stream $_test-input-buffered-file->buffer)
 7431     (clear-stream _test-output-stream)
 7432     (clear-stream $_test-output-buffered-file->buffer)
 7433     (clear-stream _test-error-stream)
 7434     (clear-stream $_test-error-buffered-file->buffer)
 7435     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7436     68/push 0/imm32
 7437     68/push 0/imm32
 7438     89/<- %edx 4/r32/esp
 7439     (tailor-exit-descriptor %edx 0x10)
 7440     #
 7441     (write _test-input-stream "fn foo {\n")
 7442     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7443     (write _test-input-stream "  var y: (addr int)\n")
 7444     (write _test-input-stream "  copy-to y, x\n")
 7445     (write _test-input-stream "}\n")
 7446     # convert
 7447     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7448     # registers except esp clobbered at this point
 7449     # restore ed
 7450     89/<- %edx 4/r32/esp
 7451     (flush _test-output-buffered-file)
 7452     (flush _test-error-buffered-file)
 7453 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7459     # check output
 7460     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 7461     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-address: error message")
 7462     # check that stop(1) was called
 7463     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 7464     # don't restore from ebp
 7465     81 0/subop/add %esp 8/imm32
 7466     # . epilogue
 7467     5d/pop-to-ebp
 7468     c3/return
 7469 
 7470 test-copy-to-deref-address:
 7471     # . prologue
 7472     55/push-ebp
 7473     89/<- %ebp 4/r32/esp
 7474     # setup
 7475     (clear-stream _test-input-stream)
 7476     (clear-stream $_test-input-buffered-file->buffer)
 7477     (clear-stream _test-output-stream)
 7478     (clear-stream $_test-output-buffered-file->buffer)
 7479     #
 7480     (write _test-input-stream "fn foo {\n")
 7481     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7482     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 7483     (write _test-input-stream "  copy-to *y, x\n")
 7484     (write _test-input-stream "}\n")
 7485     # convert
 7486     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7487     (flush _test-output-buffered-file)
 7488 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7494     # not bothering checking output
 7495     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-to-deref-address: error message")
 7496     # . epilogue
 7497     5d/pop-to-ebp
 7498     c3/return
 7499 
 7500 test-copy-to-non-scalar:
 7501     # . prologue
 7502     55/push-ebp
 7503     89/<- %ebp 4/r32/esp
 7504     # setup
 7505     (clear-stream _test-input-stream)
 7506     (clear-stream $_test-input-buffered-file->buffer)
 7507     (clear-stream _test-output-stream)
 7508     (clear-stream $_test-output-buffered-file->buffer)
 7509     (clear-stream _test-error-stream)
 7510     (clear-stream $_test-error-buffered-file->buffer)
 7511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7512     68/push 0/imm32
 7513     68/push 0/imm32
 7514     89/<- %edx 4/r32/esp
 7515     (tailor-exit-descriptor %edx 0x10)
 7516     #
 7517     (write _test-input-stream "fn foo {\n")
 7518     (write _test-input-stream "  var x: (handle int)\n")
 7519     (write _test-input-stream "  var y: int\n")
 7520     (write _test-input-stream "  copy-to y, x\n")
 7521     (write _test-input-stream "}\n")
 7522     # convert
 7523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7524     # registers except esp clobbered at this point
 7525     # restore ed
 7526     89/<- %edx 4/r32/esp
 7527     (flush _test-output-buffered-file)
 7528     (flush _test-error-buffered-file)
 7529 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7535     # check output
 7536     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-scalar: output should be empty")
 7537 #?     (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")
 7538     (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")
 7539     # check that stop(1) was called
 7540     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-scalar: exit status")
 7541     # don't restore from ebp
 7542     81 0/subop/add %esp 8/imm32
 7543     # . epilogue
 7544     5d/pop-to-ebp
 7545     c3/return
 7546 
 7547 test-compare-with-no-inout:
 7548     # . prologue
 7549     55/push-ebp
 7550     89/<- %ebp 4/r32/esp
 7551     # setup
 7552     (clear-stream _test-input-stream)
 7553     (clear-stream $_test-input-buffered-file->buffer)
 7554     (clear-stream _test-output-stream)
 7555     (clear-stream $_test-output-buffered-file->buffer)
 7556     (clear-stream _test-error-stream)
 7557     (clear-stream $_test-error-buffered-file->buffer)
 7558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7559     68/push 0/imm32
 7560     68/push 0/imm32
 7561     89/<- %edx 4/r32/esp
 7562     (tailor-exit-descriptor %edx 0x10)
 7563     #
 7564     (write _test-input-stream "fn foo {\n")
 7565     (write _test-input-stream "  var x: boolean\n")
 7566     (write _test-input-stream "  compare\n")
 7567     (write _test-input-stream "}\n")
 7568     # convert
 7569     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7570     # registers except esp clobbered at this point
 7571     # restore ed
 7572     89/<- %edx 4/r32/esp
 7573     (flush _test-output-buffered-file)
 7574     (flush _test-error-buffered-file)
 7575 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7581     # check output
 7582     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 7583     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 7584     # check that stop(1) was called
 7585     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 7586     # don't restore from ebp
 7587     81 0/subop/add %esp 8/imm32
 7588     # . epilogue
 7589     5d/pop-to-ebp
 7590     c3/return
 7591 
 7592 test-compare-with-no-input:
 7593     # . prologue
 7594     55/push-ebp
 7595     89/<- %ebp 4/r32/esp
 7596     # setup
 7597     (clear-stream _test-input-stream)
 7598     (clear-stream $_test-input-buffered-file->buffer)
 7599     (clear-stream _test-output-stream)
 7600     (clear-stream $_test-output-buffered-file->buffer)
 7601     (clear-stream _test-error-stream)
 7602     (clear-stream $_test-error-buffered-file->buffer)
 7603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7604     68/push 0/imm32
 7605     68/push 0/imm32
 7606     89/<- %edx 4/r32/esp
 7607     (tailor-exit-descriptor %edx 0x10)
 7608     #
 7609     (write _test-input-stream "fn foo {\n")
 7610     (write _test-input-stream "  var x: boolean\n")
 7611     (write _test-input-stream "  compare x\n")
 7612     (write _test-input-stream "}\n")
 7613     # convert
 7614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7615     # registers except esp clobbered at this point
 7616     # restore ed
 7617     89/<- %edx 4/r32/esp
 7618     (flush _test-output-buffered-file)
 7619     (flush _test-error-buffered-file)
 7620 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7626     # check output
 7627     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-input: output should be empty")
 7628     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-input: error message")
 7629     # check that stop(1) was called
 7630     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-input: exit status")
 7631     # don't restore from ebp
 7632     81 0/subop/add %esp 8/imm32
 7633     # . epilogue
 7634     5d/pop-to-ebp
 7635     c3/return
 7636 
 7637 test-compare-with-too-many-inouts:
 7638     # . prologue
 7639     55/push-ebp
 7640     89/<- %ebp 4/r32/esp
 7641     # setup
 7642     (clear-stream _test-input-stream)
 7643     (clear-stream $_test-input-buffered-file->buffer)
 7644     (clear-stream _test-output-stream)
 7645     (clear-stream $_test-output-buffered-file->buffer)
 7646     (clear-stream _test-error-stream)
 7647     (clear-stream $_test-error-buffered-file->buffer)
 7648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7649     68/push 0/imm32
 7650     68/push 0/imm32
 7651     89/<- %edx 4/r32/esp
 7652     (tailor-exit-descriptor %edx 0x10)
 7653     #
 7654     (write _test-input-stream "fn foo {\n")
 7655     (write _test-input-stream "  var x: boolean\n")
 7656     (write _test-input-stream "  compare x, 0, 0\n")
 7657     (write _test-input-stream "}\n")
 7658     # convert
 7659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7660     # registers except esp clobbered at this point
 7661     # restore ed
 7662     89/<- %edx 4/r32/esp
 7663     (flush _test-output-buffered-file)
 7664     (flush _test-error-buffered-file)
 7665 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7671     # check output
 7672     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 7673     (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")
 7674     # check that stop(1) was called
 7675     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 7676     # don't restore from ebp
 7677     81 0/subop/add %esp 8/imm32
 7678     # . epilogue
 7679     5d/pop-to-ebp
 7680     c3/return
 7681 
 7682 test-compare-with-output:
 7683     # . prologue
 7684     55/push-ebp
 7685     89/<- %ebp 4/r32/esp
 7686     # setup
 7687     (clear-stream _test-input-stream)
 7688     (clear-stream $_test-input-buffered-file->buffer)
 7689     (clear-stream _test-output-stream)
 7690     (clear-stream $_test-output-buffered-file->buffer)
 7691     (clear-stream _test-error-stream)
 7692     (clear-stream $_test-error-buffered-file->buffer)
 7693     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7694     68/push 0/imm32
 7695     68/push 0/imm32
 7696     89/<- %edx 4/r32/esp
 7697     (tailor-exit-descriptor %edx 0x10)
 7698     #
 7699     (write _test-input-stream "fn foo {\n")
 7700     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7701     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7702     (write _test-input-stream "  x <- compare y, 0\n")
 7703     (write _test-input-stream "}\n")
 7704     # convert
 7705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7706     # registers except esp clobbered at this point
 7707     # restore ed
 7708     89/<- %edx 4/r32/esp
 7709     (flush _test-output-buffered-file)
 7710     (flush _test-error-buffered-file)
 7711 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7717     # check output
 7718     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 7719     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 7720     # check that stop(1) was called
 7721     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 7722     # don't restore from ebp
 7723     81 0/subop/add %esp 8/imm32
 7724     # . epilogue
 7725     5d/pop-to-ebp
 7726     c3/return
 7727 
 7728 test-compare-invalid-value-to-address:
 7729     # . prologue
 7730     55/push-ebp
 7731     89/<- %ebp 4/r32/esp
 7732     # setup
 7733     (clear-stream _test-input-stream)
 7734     (clear-stream $_test-input-buffered-file->buffer)
 7735     (clear-stream _test-output-stream)
 7736     (clear-stream $_test-output-buffered-file->buffer)
 7737     (clear-stream _test-error-stream)
 7738     (clear-stream $_test-error-buffered-file->buffer)
 7739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7740     68/push 0/imm32
 7741     68/push 0/imm32
 7742     89/<- %edx 4/r32/esp
 7743     (tailor-exit-descriptor %edx 0x10)
 7744     #
 7745     (write _test-input-stream "fn foo {\n")
 7746     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7747     (write _test-input-stream "  var y: (addr int)\n")
 7748     (write _test-input-stream "  compare y, x\n")
 7749     (write _test-input-stream "}\n")
 7750     # convert
 7751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7752     # registers except esp clobbered at this point
 7753     # restore ed
 7754     89/<- %edx 4/r32/esp
 7755     (flush _test-output-buffered-file)
 7756     (flush _test-error-buffered-file)
 7757 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7763     # check output
 7764     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 7765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar"  "F - test-compare-invalid-value-to-address: error message")
 7766     # check that stop(1) was called
 7767     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 7768     # don't restore from ebp
 7769     81 0/subop/add %esp 8/imm32
 7770     # . epilogue
 7771     5d/pop-to-ebp
 7772     c3/return
 7773 
 7774 test-compare-address:
 7775     # . prologue
 7776     55/push-ebp
 7777     89/<- %ebp 4/r32/esp
 7778     # setup
 7779     (clear-stream _test-input-stream)
 7780     (clear-stream $_test-input-buffered-file->buffer)
 7781     (clear-stream _test-output-stream)
 7782     (clear-stream $_test-output-buffered-file->buffer)
 7783     #
 7784     (write _test-input-stream "fn foo {\n")
 7785     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7786     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7787     (write _test-input-stream "  compare y, x\n")
 7788     (write _test-input-stream "}\n")
 7789     # convert
 7790     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7791     (flush _test-output-buffered-file)
 7792 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7798     # not bothering checking output
 7799     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-address: error message")
 7800     # . epilogue
 7801     5d/pop-to-ebp
 7802     c3/return
 7803 
 7804 test-compare-deref-address:
 7805     # . prologue
 7806     55/push-ebp
 7807     89/<- %ebp 4/r32/esp
 7808     # setup
 7809     (clear-stream _test-input-stream)
 7810     (clear-stream $_test-input-buffered-file->buffer)
 7811     (clear-stream _test-output-stream)
 7812     (clear-stream $_test-output-buffered-file->buffer)
 7813     #
 7814     (write _test-input-stream "fn foo {\n")
 7815     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 7816     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 7817     (write _test-input-stream "  compare *y, x\n")
 7818     (write _test-input-stream "}\n")
 7819     # convert
 7820     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7821     (flush _test-output-buffered-file)
 7822 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7828     # not bothering checking output
 7829     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-deref-address: error message")
 7830     # . epilogue
 7831     5d/pop-to-ebp
 7832     c3/return
 7833 
 7834 test-compare-two-vars-in-memory:
 7835     # . prologue
 7836     55/push-ebp
 7837     89/<- %ebp 4/r32/esp
 7838     # setup
 7839     (clear-stream _test-input-stream)
 7840     (clear-stream $_test-input-buffered-file->buffer)
 7841     (clear-stream _test-output-stream)
 7842     (clear-stream $_test-output-buffered-file->buffer)
 7843     (clear-stream _test-error-stream)
 7844     (clear-stream $_test-error-buffered-file->buffer)
 7845     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7846     68/push 0/imm32
 7847     68/push 0/imm32
 7848     89/<- %edx 4/r32/esp
 7849     (tailor-exit-descriptor %edx 0x10)
 7850     #
 7851     (write _test-input-stream "fn foo {\n")
 7852     (write _test-input-stream "  var x: boolean\n")
 7853     (write _test-input-stream "  compare x, x\n")
 7854     (write _test-input-stream "}\n")
 7855     # convert
 7856     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7857     # registers except esp clobbered at this point
 7858     # restore ed
 7859     89/<- %edx 4/r32/esp
 7860     (flush _test-output-buffered-file)
 7861     (flush _test-error-buffered-file)
 7862 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7868     # check output
 7869     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 7870     (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")
 7871     # check that stop(1) was called
 7872     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 7873     # don't restore from ebp
 7874     81 0/subop/add %esp 8/imm32
 7875     # . epilogue
 7876     5d/pop-to-ebp
 7877     c3/return
 7878 
 7879 test-compare-non-scalar:
 7880     # . prologue
 7881     55/push-ebp
 7882     89/<- %ebp 4/r32/esp
 7883     # setup
 7884     (clear-stream _test-input-stream)
 7885     (clear-stream $_test-input-buffered-file->buffer)
 7886     (clear-stream _test-output-stream)
 7887     (clear-stream $_test-output-buffered-file->buffer)
 7888     (clear-stream _test-error-stream)
 7889     (clear-stream $_test-error-buffered-file->buffer)
 7890     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7891     68/push 0/imm32
 7892     68/push 0/imm32
 7893     89/<- %edx 4/r32/esp
 7894     (tailor-exit-descriptor %edx 0x10)
 7895     #
 7896     (write _test-input-stream "fn foo {\n")
 7897     (write _test-input-stream "  var x: (handle int)\n")
 7898     (write _test-input-stream "  var y: int\n")
 7899     (write _test-input-stream "  compare y, x\n")
 7900     (write _test-input-stream "}\n")
 7901     # convert
 7902     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7903     # registers except esp clobbered at this point
 7904     # restore ed
 7905     89/<- %edx 4/r32/esp
 7906     (flush _test-output-buffered-file)
 7907     (flush _test-error-buffered-file)
 7908 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7914     # check output
 7915     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 7916 #?     (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")
 7917     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 7918     # check that stop(1) was called
 7919     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 7920     # don't restore from ebp
 7921     81 0/subop/add %esp 8/imm32
 7922     # . epilogue
 7923     5d/pop-to-ebp
 7924     c3/return
 7925 
 7926 test-address-with-no-inout:
 7927     # . prologue
 7928     55/push-ebp
 7929     89/<- %ebp 4/r32/esp
 7930     # setup
 7931     (clear-stream _test-input-stream)
 7932     (clear-stream $_test-input-buffered-file->buffer)
 7933     (clear-stream _test-output-stream)
 7934     (clear-stream $_test-output-buffered-file->buffer)
 7935     (clear-stream _test-error-stream)
 7936     (clear-stream $_test-error-buffered-file->buffer)
 7937     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7938     68/push 0/imm32
 7939     68/push 0/imm32
 7940     89/<- %edx 4/r32/esp
 7941     (tailor-exit-descriptor %edx 0x10)
 7942     #
 7943     (write _test-input-stream "fn foo {\n")
 7944     (write _test-input-stream "  var x/eax: boolean <- address\n")
 7945     (write _test-input-stream "}\n")
 7946     # convert
 7947     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7948     # registers except esp clobbered at this point
 7949     # restore ed
 7950     89/<- %edx 4/r32/esp
 7951     (flush _test-output-buffered-file)
 7952     (flush _test-error-buffered-file)
 7953 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7959     # check output
 7960     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 7961     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 7962     # check that stop(1) was called
 7963     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 7964     # don't restore from ebp
 7965     81 0/subop/add %esp 8/imm32
 7966     # . epilogue
 7967     5d/pop-to-ebp
 7968     c3/return
 7969 
 7970 test-address-with-multiple-inouts:
 7971     # . prologue
 7972     55/push-ebp
 7973     89/<- %ebp 4/r32/esp
 7974     # setup
 7975     (clear-stream _test-input-stream)
 7976     (clear-stream $_test-input-buffered-file->buffer)
 7977     (clear-stream _test-output-stream)
 7978     (clear-stream $_test-output-buffered-file->buffer)
 7979     (clear-stream _test-error-stream)
 7980     (clear-stream $_test-error-buffered-file->buffer)
 7981     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7982     68/push 0/imm32
 7983     68/push 0/imm32
 7984     89/<- %edx 4/r32/esp
 7985     (tailor-exit-descriptor %edx 0x10)
 7986     #
 7987     (write _test-input-stream "fn foo {\n")
 7988     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 7989     (write _test-input-stream "}\n")
 7990     # convert
 7991     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7992     # registers except esp clobbered at this point
 7993     # restore ed
 7994     89/<- %edx 4/r32/esp
 7995     (flush _test-output-buffered-file)
 7996     (flush _test-error-buffered-file)
 7997 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8003     # check output
 8004     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 8005     (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")
 8006     # check that stop(1) was called
 8007     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 8008     # don't restore from ebp
 8009     81 0/subop/add %esp 8/imm32
 8010     # . epilogue
 8011     5d/pop-to-ebp
 8012     c3/return
 8013 
 8014 test-address-with-no-output:
 8015     # . prologue
 8016     55/push-ebp
 8017     89/<- %ebp 4/r32/esp
 8018     # setup
 8019     (clear-stream _test-input-stream)
 8020     (clear-stream $_test-input-buffered-file->buffer)
 8021     (clear-stream _test-output-stream)
 8022     (clear-stream $_test-output-buffered-file->buffer)
 8023     (clear-stream _test-error-stream)
 8024     (clear-stream $_test-error-buffered-file->buffer)
 8025     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8026     68/push 0/imm32
 8027     68/push 0/imm32
 8028     89/<- %edx 4/r32/esp
 8029     (tailor-exit-descriptor %edx 0x10)
 8030     #
 8031     (write _test-input-stream "fn foo {\n")
 8032     (write _test-input-stream "  address 0\n")
 8033     (write _test-input-stream "}\n")
 8034     # convert
 8035     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8036     # registers except esp clobbered at this point
 8037     # restore ed
 8038     89/<- %edx 4/r32/esp
 8039     (flush _test-output-buffered-file)
 8040     (flush _test-error-buffered-file)
 8041 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8047     # check output
 8048     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 8049     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 8050     # check that stop(1) was called
 8051     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 8052     # don't restore from ebp
 8053     81 0/subop/add %esp 8/imm32
 8054     # . epilogue
 8055     5d/pop-to-ebp
 8056     c3/return
 8057 
 8058 test-address-with-multiple-outputs:
 8059     # . prologue
 8060     55/push-ebp
 8061     89/<- %ebp 4/r32/esp
 8062     # setup
 8063     (clear-stream _test-input-stream)
 8064     (clear-stream $_test-input-buffered-file->buffer)
 8065     (clear-stream _test-output-stream)
 8066     (clear-stream $_test-output-buffered-file->buffer)
 8067     (clear-stream _test-error-stream)
 8068     (clear-stream $_test-error-buffered-file->buffer)
 8069     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8070     68/push 0/imm32
 8071     68/push 0/imm32
 8072     89/<- %edx 4/r32/esp
 8073     (tailor-exit-descriptor %edx 0x10)
 8074     #
 8075     (write _test-input-stream "fn foo {\n")
 8076     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8077     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8078     (write _test-input-stream "  x, y <- address 0\n")
 8079     (write _test-input-stream "}\n")
 8080     # convert
 8081     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8082     # registers except esp clobbered at this point
 8083     # restore ed
 8084     89/<- %edx 4/r32/esp
 8085     (flush _test-output-buffered-file)
 8086     (flush _test-error-buffered-file)
 8087 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8093     # check output
 8094     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 8095     (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")
 8096     # check that stop(1) was called
 8097     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 8098     # don't restore from ebp
 8099     81 0/subop/add %esp 8/imm32
 8100     # . epilogue
 8101     5d/pop-to-ebp
 8102     c3/return
 8103 
 8104 # silly but it works
 8105 test-address-of-deref:
 8106     # . prologue
 8107     55/push-ebp
 8108     89/<- %ebp 4/r32/esp
 8109     # setup
 8110     (clear-stream _test-input-stream)
 8111     (clear-stream $_test-input-buffered-file->buffer)
 8112     (clear-stream _test-output-stream)
 8113     (clear-stream $_test-output-buffered-file->buffer)
 8114     #
 8115     (write _test-input-stream "fn foo {\n")
 8116     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8117     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 8118     (write _test-input-stream "}\n")
 8119     # convert
 8120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8121     (flush _test-output-buffered-file)
 8122 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8128     # not bothering checking output
 8129     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-of-deref: error message")
 8130     # . epilogue
 8131     5d/pop-to-ebp
 8132     c3/return
 8133 
 8134 test-address-to-non-register:
 8135     # . prologue
 8136     55/push-ebp
 8137     89/<- %ebp 4/r32/esp
 8138     # setup
 8139     (clear-stream _test-input-stream)
 8140     (clear-stream $_test-input-buffered-file->buffer)
 8141     (clear-stream _test-output-stream)
 8142     (clear-stream $_test-output-buffered-file->buffer)
 8143     (clear-stream _test-error-stream)
 8144     (clear-stream $_test-error-buffered-file->buffer)
 8145     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8146     68/push 0/imm32
 8147     68/push 0/imm32
 8148     89/<- %edx 4/r32/esp
 8149     (tailor-exit-descriptor %edx 0x10)
 8150     #
 8151     (write _test-input-stream "fn foo {\n")
 8152     (write _test-input-stream "  var x: (addr int)\n")
 8153     (write _test-input-stream "  x <- address 0\n")
 8154     (write _test-input-stream "}\n")
 8155     # convert
 8156     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8157     # registers except esp clobbered at this point
 8158     # restore ed
 8159     89/<- %edx 4/r32/esp
 8160     (flush _test-output-buffered-file)
 8161     (flush _test-error-buffered-file)
 8162 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8168     # check output
 8169     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 8170     (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")
 8171     # check that stop(1) was called
 8172     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 8173     # don't restore from ebp
 8174     81 0/subop/add %esp 8/imm32
 8175     # . epilogue
 8176     5d/pop-to-ebp
 8177     c3/return
 8178 
 8179 test-address-with-wrong-type:
 8180     # . prologue
 8181     55/push-ebp
 8182     89/<- %ebp 4/r32/esp
 8183     # setup
 8184     (clear-stream _test-input-stream)
 8185     (clear-stream $_test-input-buffered-file->buffer)
 8186     (clear-stream _test-output-stream)
 8187     (clear-stream $_test-output-buffered-file->buffer)
 8188     (clear-stream _test-error-stream)
 8189     (clear-stream $_test-error-buffered-file->buffer)
 8190     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8191     68/push 0/imm32
 8192     68/push 0/imm32
 8193     89/<- %edx 4/r32/esp
 8194     (tailor-exit-descriptor %edx 0x10)
 8195     #
 8196     (write _test-input-stream "fn foo {\n")
 8197     (write _test-input-stream "  var x: int\n")
 8198     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 8199     (write _test-input-stream "}\n")
 8200     # convert
 8201     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8202     # registers except esp clobbered at this point
 8203     # restore ed
 8204     89/<- %edx 4/r32/esp
 8205     (flush _test-output-buffered-file)
 8206     (flush _test-error-buffered-file)
 8207 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8213     # check output
 8214     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 8215     (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")
 8216     # check that stop(1) was called
 8217     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 8218     # don't restore from ebp
 8219     81 0/subop/add %esp 8/imm32
 8220     # . epilogue
 8221     5d/pop-to-ebp
 8222     c3/return
 8223 
 8224 test-address-with-right-type-for-array:
 8225     # . prologue
 8226     55/push-ebp
 8227     89/<- %ebp 4/r32/esp
 8228     # setup
 8229     (clear-stream _test-input-stream)
 8230     (clear-stream $_test-input-buffered-file->buffer)
 8231     (clear-stream _test-output-stream)
 8232     (clear-stream $_test-output-buffered-file->buffer)
 8233     #
 8234     (write _test-input-stream "fn foo {\n")
 8235     (write _test-input-stream "  var x: (array int 3)\n")
 8236     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 8237     (write _test-input-stream "}\n")
 8238     # convert
 8239     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8240     (flush _test-output-buffered-file)
 8241 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8247     # no error
 8248     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-array: error message")
 8249     # don't bother checking output
 8250     # . epilogue
 8251     89/<- %esp 5/r32/ebp
 8252     5d/pop-to-ebp
 8253     c3/return
 8254 
 8255 test-address-with-right-type-for-stream:
 8256     # . prologue
 8257     55/push-ebp
 8258     89/<- %ebp 4/r32/esp
 8259     # setup
 8260     (clear-stream _test-input-stream)
 8261     (clear-stream $_test-input-buffered-file->buffer)
 8262     (clear-stream _test-output-stream)
 8263     (clear-stream $_test-output-buffered-file->buffer)
 8264     #
 8265     (write _test-input-stream "fn foo {\n")
 8266     (write _test-input-stream "  var x: (stream int 3)\n")
 8267     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 8268     (write _test-input-stream "}\n")
 8269     # convert
 8270     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8271     (flush _test-output-buffered-file)
 8272 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8278     # no error
 8279     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-stream: error message")
 8280     # don't bother checking output
 8281     # . epilogue
 8282     89/<- %esp 5/r32/ebp
 8283     5d/pop-to-ebp
 8284     c3/return
 8285 
 8286 test-get-with-wrong-field:
 8287     # . prologue
 8288     55/push-ebp
 8289     89/<- %ebp 4/r32/esp
 8290     # setup
 8291     (clear-stream _test-input-stream)
 8292     (clear-stream $_test-input-buffered-file->buffer)
 8293     (clear-stream _test-output-stream)
 8294     (clear-stream $_test-output-buffered-file->buffer)
 8295     (clear-stream _test-error-stream)
 8296     (clear-stream $_test-error-buffered-file->buffer)
 8297     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8298     68/push 0/imm32
 8299     68/push 0/imm32
 8300     89/<- %edx 4/r32/esp
 8301     (tailor-exit-descriptor %edx 0x10)
 8302     #
 8303     (write _test-input-stream "fn foo {\n")
 8304     (write _test-input-stream "  var a: t\n")
 8305     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8306     (write _test-input-stream "}\n")
 8307     (write _test-input-stream "type t {\n")
 8308     (write _test-input-stream "  x: int\n")
 8309     (write _test-input-stream "}\n")
 8310     # convert
 8311     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8312     # registers except esp clobbered at this point
 8313     # restore ed
 8314     89/<- %edx 4/r32/esp
 8315     (flush _test-output-buffered-file)
 8316     (flush _test-error-buffered-file)
 8317 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8323     # check output
 8324     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 8325     (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")
 8326     # check that stop(1) was called
 8327     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 8328     # don't restore from ebp
 8329     81 0/subop/add %esp 8/imm32
 8330     # . epilogue
 8331     5d/pop-to-ebp
 8332     c3/return
 8333 
 8334 test-get-with-wrong-base-type:
 8335     # . prologue
 8336     55/push-ebp
 8337     89/<- %ebp 4/r32/esp
 8338     # setup
 8339     (clear-stream _test-input-stream)
 8340     (clear-stream $_test-input-buffered-file->buffer)
 8341     (clear-stream _test-output-stream)
 8342     (clear-stream $_test-output-buffered-file->buffer)
 8343     (clear-stream _test-error-stream)
 8344     (clear-stream $_test-error-buffered-file->buffer)
 8345     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8346     68/push 0/imm32
 8347     68/push 0/imm32
 8348     89/<- %edx 4/r32/esp
 8349     (tailor-exit-descriptor %edx 0x10)
 8350     #
 8351     (write _test-input-stream "fn foo {\n")
 8352     (write _test-input-stream "  var a: int\n")
 8353     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8354     (write _test-input-stream "}\n")
 8355     # convert
 8356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8357     # registers except esp clobbered at this point
 8358     # restore ed
 8359     89/<- %edx 4/r32/esp
 8360     (flush _test-output-buffered-file)
 8361     (flush _test-error-buffered-file)
 8362 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8368     # check output
 8369     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 8370     (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")
 8371     # check that stop(1) was called
 8372     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 8373     # don't restore from ebp
 8374     81 0/subop/add %esp 8/imm32
 8375     # . epilogue
 8376     5d/pop-to-ebp
 8377     c3/return
 8378 
 8379 test-get-with-wrong-base-type-2:
 8380     # . prologue
 8381     55/push-ebp
 8382     89/<- %ebp 4/r32/esp
 8383     # setup
 8384     (clear-stream _test-input-stream)
 8385     (clear-stream $_test-input-buffered-file->buffer)
 8386     (clear-stream _test-output-stream)
 8387     (clear-stream $_test-output-buffered-file->buffer)
 8388     (clear-stream _test-error-stream)
 8389     (clear-stream $_test-error-buffered-file->buffer)
 8390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8391     68/push 0/imm32
 8392     68/push 0/imm32
 8393     89/<- %edx 4/r32/esp
 8394     (tailor-exit-descriptor %edx 0x10)
 8395     #
 8396     (write _test-input-stream "fn foo {\n")
 8397     (write _test-input-stream "  var a: (addr t)\n")
 8398     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8399     (write _test-input-stream "}\n")
 8400     (write _test-input-stream "type t {\n")
 8401     (write _test-input-stream "  x: int\n")
 8402     (write _test-input-stream "}\n")
 8403     # convert
 8404     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8405     # registers except esp clobbered at this point
 8406     # restore ed
 8407     89/<- %edx 4/r32/esp
 8408     (flush _test-output-buffered-file)
 8409     (flush _test-error-buffered-file)
 8410 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8416     # check output
 8417     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 8418     (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")
 8419     # check that stop(1) was called
 8420     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 8421     # don't restore from ebp
 8422     81 0/subop/add %esp 8/imm32
 8423     # . epilogue
 8424     5d/pop-to-ebp
 8425     c3/return
 8426 
 8427 test-get-with-wrong-base-type-3:
 8428     # . prologue
 8429     55/push-ebp
 8430     89/<- %ebp 4/r32/esp
 8431     # setup
 8432     (clear-stream _test-input-stream)
 8433     (clear-stream $_test-input-buffered-file->buffer)
 8434     (clear-stream _test-output-stream)
 8435     (clear-stream $_test-output-buffered-file->buffer)
 8436     (clear-stream _test-error-stream)
 8437     (clear-stream $_test-error-buffered-file->buffer)
 8438     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8439     68/push 0/imm32
 8440     68/push 0/imm32
 8441     89/<- %edx 4/r32/esp
 8442     (tailor-exit-descriptor %edx 0x10)
 8443     #
 8444     (write _test-input-stream "fn foo {\n")
 8445     (write _test-input-stream "  var a: (handle int)\n")
 8446     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8447     (write _test-input-stream "}\n")
 8448     # convert
 8449     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8450     # registers except esp clobbered at this point
 8451     # restore ed
 8452     89/<- %edx 4/r32/esp
 8453     (flush _test-output-buffered-file)
 8454     (flush _test-error-buffered-file)
 8455 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8461     # check output
 8462     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
 8463     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type-3: error message")
 8464     # check that stop(1) was called
 8465     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
 8466     # don't restore from ebp
 8467     81 0/subop/add %esp 8/imm32
 8468     # . epilogue
 8469     5d/pop-to-ebp
 8470     c3/return
 8471 
 8472 test-get-with-wrong-offset-type:
 8473     # . prologue
 8474     55/push-ebp
 8475     89/<- %ebp 4/r32/esp
 8476     # setup
 8477     (clear-stream _test-input-stream)
 8478     (clear-stream $_test-input-buffered-file->buffer)
 8479     (clear-stream _test-output-stream)
 8480     (clear-stream $_test-output-buffered-file->buffer)
 8481     (clear-stream _test-error-stream)
 8482     (clear-stream $_test-error-buffered-file->buffer)
 8483     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8484     68/push 0/imm32
 8485     68/push 0/imm32
 8486     89/<- %edx 4/r32/esp
 8487     (tailor-exit-descriptor %edx 0x10)
 8488     #
 8489     (write _test-input-stream "fn foo {\n")
 8490     (write _test-input-stream "  var a: t\n")
 8491     (write _test-input-stream "  var b: int\n")
 8492     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 8493     (write _test-input-stream "}\n")
 8494     (write _test-input-stream "type t {\n")
 8495     (write _test-input-stream "  x: int\n")
 8496     (write _test-input-stream "}\n")
 8497     # convert
 8498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8499     # registers except esp clobbered at this point
 8500     # restore ed
 8501     89/<- %edx 4/r32/esp
 8502     (flush _test-output-buffered-file)
 8503     (flush _test-error-buffered-file)
 8504 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8510     # check output
 8511     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 8512     (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")
 8513     # check that stop(1) was called
 8514     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 8515     # don't restore from ebp
 8516     81 0/subop/add %esp 8/imm32
 8517     # . epilogue
 8518     5d/pop-to-ebp
 8519     c3/return
 8520 
 8521 test-get-with-wrong-output-type:
 8522     # . prologue
 8523     55/push-ebp
 8524     89/<- %ebp 4/r32/esp
 8525     # setup
 8526     (clear-stream _test-input-stream)
 8527     (clear-stream $_test-input-buffered-file->buffer)
 8528     (clear-stream _test-output-stream)
 8529     (clear-stream $_test-output-buffered-file->buffer)
 8530     (clear-stream _test-error-stream)
 8531     (clear-stream $_test-error-buffered-file->buffer)
 8532     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8533     68/push 0/imm32
 8534     68/push 0/imm32
 8535     89/<- %edx 4/r32/esp
 8536     (tailor-exit-descriptor %edx 0x10)
 8537     #
 8538     (write _test-input-stream "fn foo {\n")
 8539     (write _test-input-stream "  var a: t\n")
 8540     (write _test-input-stream "  var c: (addr int)\n")
 8541     (write _test-input-stream "  c <- get a, x\n")
 8542     (write _test-input-stream "}\n")
 8543     (write _test-input-stream "type t {\n")
 8544     (write _test-input-stream "  x: int\n")
 8545     (write _test-input-stream "}\n")
 8546     # convert
 8547     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8548     # registers except esp clobbered at this point
 8549     # restore ed
 8550     89/<- %edx 4/r32/esp
 8551     (flush _test-output-buffered-file)
 8552     (flush _test-error-buffered-file)
 8553 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8559     # check output
 8560     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 8561     (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")
 8562     # check that stop(1) was called
 8563     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 8564     # don't restore from ebp
 8565     81 0/subop/add %esp 8/imm32
 8566     # . epilogue
 8567     5d/pop-to-ebp
 8568     c3/return
 8569 
 8570 test-get-with-wrong-output-type-2:
 8571     # . prologue
 8572     55/push-ebp
 8573     89/<- %ebp 4/r32/esp
 8574     # setup
 8575     (clear-stream _test-input-stream)
 8576     (clear-stream $_test-input-buffered-file->buffer)
 8577     (clear-stream _test-output-stream)
 8578     (clear-stream $_test-output-buffered-file->buffer)
 8579     (clear-stream _test-error-stream)
 8580     (clear-stream $_test-error-buffered-file->buffer)
 8581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8582     68/push 0/imm32
 8583     68/push 0/imm32
 8584     89/<- %edx 4/r32/esp
 8585     (tailor-exit-descriptor %edx 0x10)
 8586     #
 8587     (write _test-input-stream "fn foo {\n")
 8588     (write _test-input-stream "  var a: t\n")
 8589     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 8590     (write _test-input-stream "}\n")
 8591     (write _test-input-stream "type t {\n")
 8592     (write _test-input-stream "  x: int\n")
 8593     (write _test-input-stream "}\n")
 8594     # convert
 8595     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8596     # registers except esp clobbered at this point
 8597     # restore ed
 8598     89/<- %edx 4/r32/esp
 8599     (flush _test-output-buffered-file)
 8600     (flush _test-error-buffered-file)
 8601 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8607     # check output
 8608     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 8609     (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")
 8610     # check that stop(1) was called
 8611     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 8612     # don't restore from ebp
 8613     81 0/subop/add %esp 8/imm32
 8614     # . epilogue
 8615     5d/pop-to-ebp
 8616     c3/return
 8617 
 8618 test-get-with-wrong-output-type-3:
 8619     # . prologue
 8620     55/push-ebp
 8621     89/<- %ebp 4/r32/esp
 8622     # setup
 8623     (clear-stream _test-input-stream)
 8624     (clear-stream $_test-input-buffered-file->buffer)
 8625     (clear-stream _test-output-stream)
 8626     (clear-stream $_test-output-buffered-file->buffer)
 8627     (clear-stream _test-error-stream)
 8628     (clear-stream $_test-error-buffered-file->buffer)
 8629     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8630     68/push 0/imm32
 8631     68/push 0/imm32
 8632     89/<- %edx 4/r32/esp
 8633     (tailor-exit-descriptor %edx 0x10)
 8634     #
 8635     (write _test-input-stream "fn foo {\n")
 8636     (write _test-input-stream "  var a: t\n")
 8637     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 8638     (write _test-input-stream "}\n")
 8639     (write _test-input-stream "type t {\n")
 8640     (write _test-input-stream "  x: int\n")
 8641     (write _test-input-stream "}\n")
 8642     # convert
 8643     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8644     # registers except esp clobbered at this point
 8645     # restore ed
 8646     89/<- %edx 4/r32/esp
 8647     (flush _test-output-buffered-file)
 8648     (flush _test-error-buffered-file)
 8649 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8655     # check output
 8656     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 8657     (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")
 8658     # check that stop(1) was called
 8659     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 8660     # don't restore from ebp
 8661     81 0/subop/add %esp 8/imm32
 8662     # . epilogue
 8663     5d/pop-to-ebp
 8664     c3/return
 8665 
 8666 test-get-with-wrong-output-type-4:
 8667     # . prologue
 8668     55/push-ebp
 8669     89/<- %ebp 4/r32/esp
 8670     # setup
 8671     (clear-stream _test-input-stream)
 8672     (clear-stream $_test-input-buffered-file->buffer)
 8673     (clear-stream _test-output-stream)
 8674     (clear-stream $_test-output-buffered-file->buffer)
 8675     (clear-stream _test-error-stream)
 8676     (clear-stream $_test-error-buffered-file->buffer)
 8677     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8678     68/push 0/imm32
 8679     68/push 0/imm32
 8680     89/<- %edx 4/r32/esp
 8681     (tailor-exit-descriptor %edx 0x10)
 8682     #
 8683     (write _test-input-stream "fn foo {\n")
 8684     (write _test-input-stream "  var a: t\n")
 8685     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 8686     (write _test-input-stream "}\n")
 8687     (write _test-input-stream "type t {\n")
 8688     (write _test-input-stream "  x: int\n")
 8689     (write _test-input-stream "}\n")
 8690     # convert
 8691     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8692     # registers except esp clobbered at this point
 8693     # restore ed
 8694     89/<- %edx 4/r32/esp
 8695     (flush _test-output-buffered-file)
 8696     (flush _test-error-buffered-file)
 8697 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8703     # check output
 8704     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 8705     (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")
 8706     # check that stop(1) was called
 8707     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 8708     # don't restore from ebp
 8709     81 0/subop/add %esp 8/imm32
 8710     # . epilogue
 8711     5d/pop-to-ebp
 8712     c3/return
 8713 
 8714 test-get-with-wrong-output-type-5:
 8715     # . prologue
 8716     55/push-ebp
 8717     89/<- %ebp 4/r32/esp
 8718     # setup
 8719     (clear-stream _test-input-stream)
 8720     (clear-stream $_test-input-buffered-file->buffer)
 8721     (clear-stream _test-output-stream)
 8722     (clear-stream $_test-output-buffered-file->buffer)
 8723     #
 8724     (write _test-input-stream "fn foo {\n")
 8725     (write _test-input-stream "  var a: t\n")
 8726     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 8727     (write _test-input-stream "}\n")
 8728     (write _test-input-stream "type t {\n")
 8729     (write _test-input-stream "  x: (handle int)\n")
 8730     (write _test-input-stream "}\n")
 8731     # convert
 8732     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8733     (flush _test-output-buffered-file)
 8734     # no errors
 8735     # . epilogue
 8736     89/<- %esp 5/r32/ebp
 8737     5d/pop-to-ebp
 8738     c3/return
 8739 
 8740 test-get-with-too-few-inouts:
 8741     # . prologue
 8742     55/push-ebp
 8743     89/<- %ebp 4/r32/esp
 8744     # setup
 8745     (clear-stream _test-input-stream)
 8746     (clear-stream $_test-input-buffered-file->buffer)
 8747     (clear-stream _test-output-stream)
 8748     (clear-stream $_test-output-buffered-file->buffer)
 8749     (clear-stream _test-error-stream)
 8750     (clear-stream $_test-error-buffered-file->buffer)
 8751     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8752     68/push 0/imm32
 8753     68/push 0/imm32
 8754     89/<- %edx 4/r32/esp
 8755     (tailor-exit-descriptor %edx 0x10)
 8756     #
 8757     (write _test-input-stream "fn foo {\n")
 8758     (write _test-input-stream "  var a: t\n")
 8759     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 8760     (write _test-input-stream "}\n")
 8761     (write _test-input-stream "type t {\n")
 8762     (write _test-input-stream "  x: int\n")
 8763     (write _test-input-stream "}\n")
 8764     # convert
 8765     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8766     # registers except esp clobbered at this point
 8767     # restore ed
 8768     89/<- %edx 4/r32/esp
 8769     (flush _test-output-buffered-file)
 8770     (flush _test-error-buffered-file)
 8771 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8777     # check output
 8778     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 8779     (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")
 8780     # check that stop(1) was called
 8781     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 8782     # don't restore from ebp
 8783     81 0/subop/add %esp 8/imm32
 8784     # . epilogue
 8785     5d/pop-to-ebp
 8786     c3/return
 8787 
 8788 test-get-with-too-many-inouts:
 8789     # . prologue
 8790     55/push-ebp
 8791     89/<- %ebp 4/r32/esp
 8792     # setup
 8793     (clear-stream _test-input-stream)
 8794     (clear-stream $_test-input-buffered-file->buffer)
 8795     (clear-stream _test-output-stream)
 8796     (clear-stream $_test-output-buffered-file->buffer)
 8797     (clear-stream _test-error-stream)
 8798     (clear-stream $_test-error-buffered-file->buffer)
 8799     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8800     68/push 0/imm32
 8801     68/push 0/imm32
 8802     89/<- %edx 4/r32/esp
 8803     (tailor-exit-descriptor %edx 0x10)
 8804     #
 8805     (write _test-input-stream "fn foo {\n")
 8806     (write _test-input-stream "  var a: t\n")
 8807     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 8808     (write _test-input-stream "}\n")
 8809     (write _test-input-stream "type t {\n")
 8810     (write _test-input-stream "  x: int\n")
 8811     (write _test-input-stream "}\n")
 8812     # convert
 8813     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8814     # registers except esp clobbered at this point
 8815     # restore ed
 8816     89/<- %edx 4/r32/esp
 8817     (flush _test-output-buffered-file)
 8818     (flush _test-error-buffered-file)
 8819 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8825     # check output
 8826     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 8827     (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")
 8828     # check that stop(1) was called
 8829     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 8830     # don't restore from ebp
 8831     81 0/subop/add %esp 8/imm32
 8832     # . epilogue
 8833     5d/pop-to-ebp
 8834     c3/return
 8835 
 8836 test-get-with-no-output:
 8837     # . prologue
 8838     55/push-ebp
 8839     89/<- %ebp 4/r32/esp
 8840     # setup
 8841     (clear-stream _test-input-stream)
 8842     (clear-stream $_test-input-buffered-file->buffer)
 8843     (clear-stream _test-output-stream)
 8844     (clear-stream $_test-output-buffered-file->buffer)
 8845     (clear-stream _test-error-stream)
 8846     (clear-stream $_test-error-buffered-file->buffer)
 8847     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8848     68/push 0/imm32
 8849     68/push 0/imm32
 8850     89/<- %edx 4/r32/esp
 8851     (tailor-exit-descriptor %edx 0x10)
 8852     #
 8853     (write _test-input-stream "fn foo {\n")
 8854     (write _test-input-stream "  var a: t\n")
 8855     (write _test-input-stream "  get a, x\n")
 8856     (write _test-input-stream "}\n")
 8857     (write _test-input-stream "type t {\n")
 8858     (write _test-input-stream "  x: int\n")
 8859     (write _test-input-stream "}\n")
 8860     # convert
 8861     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8862     # registers except esp clobbered at this point
 8863     # restore ed
 8864     89/<- %edx 4/r32/esp
 8865     (flush _test-output-buffered-file)
 8866     (flush _test-error-buffered-file)
 8867 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8873     # check output
 8874     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 8875     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 8876     # check that stop(1) was called
 8877     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 8878     # don't restore from ebp
 8879     81 0/subop/add %esp 8/imm32
 8880     # . epilogue
 8881     5d/pop-to-ebp
 8882     c3/return
 8883 
 8884 test-get-with-too-many-outputs:
 8885     # . prologue
 8886     55/push-ebp
 8887     89/<- %ebp 4/r32/esp
 8888     # setup
 8889     (clear-stream _test-input-stream)
 8890     (clear-stream $_test-input-buffered-file->buffer)
 8891     (clear-stream _test-output-stream)
 8892     (clear-stream $_test-output-buffered-file->buffer)
 8893     (clear-stream _test-error-stream)
 8894     (clear-stream $_test-error-buffered-file->buffer)
 8895     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8896     68/push 0/imm32
 8897     68/push 0/imm32
 8898     89/<- %edx 4/r32/esp
 8899     (tailor-exit-descriptor %edx 0x10)
 8900     #
 8901     (write _test-input-stream "fn foo {\n")
 8902     (write _test-input-stream "  var a: t\n")
 8903     (write _test-input-stream "  var b: int\n")
 8904     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 8905     (write _test-input-stream "  c, b <- get a, x\n")
 8906     (write _test-input-stream "}\n")
 8907     (write _test-input-stream "type t {\n")
 8908     (write _test-input-stream "  x: int\n")
 8909     (write _test-input-stream "}\n")
 8910     # convert
 8911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8912     # registers except esp clobbered at this point
 8913     # restore ed
 8914     89/<- %edx 4/r32/esp
 8915     (flush _test-output-buffered-file)
 8916     (flush _test-error-buffered-file)
 8917 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8923     # check output
 8924     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 8925     (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")
 8926     # check that stop(1) was called
 8927     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 8928     # don't restore from ebp
 8929     81 0/subop/add %esp 8/imm32
 8930     # . epilogue
 8931     5d/pop-to-ebp
 8932     c3/return
 8933 
 8934 test-convert-array-of-user-defined-types:
 8935     # . prologue
 8936     55/push-ebp
 8937     89/<- %ebp 4/r32/esp
 8938     # setup
 8939     (clear-stream _test-input-stream)
 8940     (clear-stream $_test-input-buffered-file->buffer)
 8941     (clear-stream _test-output-stream)
 8942     (clear-stream $_test-output-buffered-file->buffer)
 8943     #
 8944     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 8945     (write _test-input-stream "  x: int\n")
 8946     (write _test-input-stream "  y: int\n")
 8947     (write _test-input-stream "}\n")
 8948     (write _test-input-stream "fn foo {\n")
 8949     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 8950     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 8951     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 8952     (write _test-input-stream "}\n")
 8953     # convert
 8954     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8955     (flush _test-output-buffered-file)
 8956 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8962     # check output
 8963     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 8964     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 8965     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 8966     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 8967     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 8968     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 8969     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 8970     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 8971     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 8972     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 8973     (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")
 8974     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/13")
 8975     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/14")
 8976     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/15")
 8977     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/16")
 8978     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/17")
 8979     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/18")
 8980     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/19")
 8981     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/20")
 8982     # . epilogue
 8983     89/<- %esp 5/r32/ebp
 8984     5d/pop-to-ebp
 8985     c3/return
 8986 
 8987 test-convert-length-of-array-of-user-defined-types-to-eax:
 8988     # . prologue
 8989     55/push-ebp
 8990     89/<- %ebp 4/r32/esp
 8991     # setup
 8992     (clear-stream _test-input-stream)
 8993     (clear-stream $_test-input-buffered-file->buffer)
 8994     (clear-stream _test-output-stream)
 8995     (clear-stream $_test-output-buffered-file->buffer)
 8996     #
 8997     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 8998     (write _test-input-stream "  x: int\n")
 8999     (write _test-input-stream "  y: int\n")
 9000     (write _test-input-stream "  z: int\n")
 9001     (write _test-input-stream "}\n")
 9002     (write _test-input-stream "fn foo {\n")
 9003     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9004     (write _test-input-stream "  var x/eax: int <- length arr\n")
 9005     (write _test-input-stream "}\n")
 9006     # convert
 9007     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9008     (flush _test-output-buffered-file)
 9009 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9015     # check output
 9016     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 9017     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 9018     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 9019     (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")
 9020     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 9021     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 9022     # var arr
 9023     (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")
 9024     (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")
 9025     # length instruction
 9026     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 9027     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 9028     (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")
 9029     (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")
 9030     (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")
 9031     (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")
 9032     (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")
 9033     (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")
 9034     # reclaim arr
 9035     (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")
 9036     #
 9037     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 9038     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 9039     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 9040     (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")
 9041     (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")
 9042     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 9043     # . epilogue
 9044     89/<- %esp 5/r32/ebp
 9045     5d/pop-to-ebp
 9046     c3/return
 9047 
 9048 test-convert-length-of-array-of-user-defined-types-to-ecx:
 9049     # . prologue
 9050     55/push-ebp
 9051     89/<- %ebp 4/r32/esp
 9052     # setup
 9053     (clear-stream _test-input-stream)
 9054     (clear-stream $_test-input-buffered-file->buffer)
 9055     (clear-stream _test-output-stream)
 9056     (clear-stream $_test-output-buffered-file->buffer)
 9057     #
 9058     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9059     (write _test-input-stream "  x: int\n")
 9060     (write _test-input-stream "  y: int\n")
 9061     (write _test-input-stream "  z: int\n")
 9062     (write _test-input-stream "}\n")
 9063     (write _test-input-stream "fn foo {\n")
 9064     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9065     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 9066     (write _test-input-stream "}\n")
 9067     # convert
 9068     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9069     (flush _test-output-buffered-file)
 9070 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9076     # check output
 9077     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 9078     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 9079     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 9080     (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")
 9081     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 9082     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 9083     # var a
 9084     (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")
 9085     (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")
 9086     # var x
 9087     (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")
 9088     # length instruction
 9089     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 9090     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 9091     (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")
 9092     (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")
 9093     (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")
 9094     (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")
 9095     (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")
 9096     (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")
 9097     (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")
 9098     # reclaim x
 9099     (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")
 9100     # reclaim a
 9101     (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")
 9102     #
 9103     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 9104     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 9105     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 9106     (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")
 9107     (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")
 9108     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 9109     # . epilogue
 9110     89/<- %esp 5/r32/ebp
 9111     5d/pop-to-ebp
 9112     c3/return
 9113 
 9114 test-convert-length-of-array-of-user-defined-types-to-edx:
 9115     # . prologue
 9116     55/push-ebp
 9117     89/<- %ebp 4/r32/esp
 9118     # setup
 9119     (clear-stream _test-input-stream)
 9120     (clear-stream $_test-input-buffered-file->buffer)
 9121     (clear-stream _test-output-stream)
 9122     (clear-stream $_test-output-buffered-file->buffer)
 9123     #
 9124     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9125     (write _test-input-stream "  x: int\n")
 9126     (write _test-input-stream "  y: int\n")
 9127     (write _test-input-stream "  z: int\n")
 9128     (write _test-input-stream "}\n")
 9129     (write _test-input-stream "fn foo {\n")
 9130     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9131     (write _test-input-stream "  var x/edx: int <- length arr\n")
 9132     (write _test-input-stream "}\n")
 9133     # convert
 9134     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9135     (flush _test-output-buffered-file)
 9136 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9142     # check output
 9143     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 9144     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 9145     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 9146     (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")
 9147     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 9148     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 9149     # var a
 9150     (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")
 9151     (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")
 9152     # var x
 9153     (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")
 9154     # length instruction
 9155     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 9156     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 9157     (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")
 9158     (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")
 9159     (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")
 9160     (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")
 9161     (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")
 9162     (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")
 9163     (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")
 9164     # reclaim x
 9165     (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")
 9166     # reclaim a
 9167     (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")
 9168     #
 9169     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 9170     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 9171     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 9172     (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")
 9173     (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")
 9174     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 9175     # . epilogue
 9176     89/<- %esp 5/r32/ebp
 9177     5d/pop-to-ebp
 9178     c3/return
 9179 
 9180 test-convert-length-of-array-of-user-defined-types:
 9181     # . prologue
 9182     55/push-ebp
 9183     89/<- %ebp 4/r32/esp
 9184     # setup
 9185     (clear-stream _test-input-stream)
 9186     (clear-stream $_test-input-buffered-file->buffer)
 9187     (clear-stream _test-output-stream)
 9188     (clear-stream $_test-output-buffered-file->buffer)
 9189     #
 9190     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 9191     (write _test-input-stream "  x: int\n")
 9192     (write _test-input-stream "  y: int\n")
 9193     (write _test-input-stream "  z: int\n")
 9194     (write _test-input-stream "}\n")
 9195     (write _test-input-stream "fn foo {\n")
 9196     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9197     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 9198     (write _test-input-stream "}\n")
 9199     # convert
 9200     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9201     (flush _test-output-buffered-file)
 9202 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9208     # check output
 9209     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 9210     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 9211     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 9212     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 9213     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 9214     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 9215     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 9216     (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")
 9217     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 9218     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 9219     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 9220     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 9221     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 9222     (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")
 9223     (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")
 9224     (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")
 9225     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 9226     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 9227     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 9228     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 9229     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 9230     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 9231     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 9232     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 9233     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 9234     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 9235     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 9236     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 9237     # . epilogue
 9238     89/<- %esp 5/r32/ebp
 9239     5d/pop-to-ebp
 9240     c3/return
 9241 
 9242 test-index-with-non-array-atom-base-type:
 9243     # . prologue
 9244     55/push-ebp
 9245     89/<- %ebp 4/r32/esp
 9246     # setup
 9247     (clear-stream _test-input-stream)
 9248     (clear-stream $_test-input-buffered-file->buffer)
 9249     (clear-stream _test-output-stream)
 9250     (clear-stream $_test-output-buffered-file->buffer)
 9251     (clear-stream _test-error-stream)
 9252     (clear-stream $_test-error-buffered-file->buffer)
 9253     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9254     68/push 0/imm32
 9255     68/push 0/imm32
 9256     89/<- %edx 4/r32/esp
 9257     (tailor-exit-descriptor %edx 0x10)
 9258     #
 9259     (write _test-input-stream "fn foo {\n")
 9260     (write _test-input-stream "  var a: int\n")
 9261     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9262     (write _test-input-stream "}\n")
 9263     # convert
 9264     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9265     # registers except esp clobbered at this point
 9266     # restore ed
 9267     89/<- %edx 4/r32/esp
 9268     (flush _test-output-buffered-file)
 9269     (flush _test-error-buffered-file)
 9270 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9276     # check output
 9277     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 9278     (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")
 9279     # check that stop(1) was called
 9280     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 9281     # don't restore from ebp
 9282     81 0/subop/add %esp 8/imm32
 9283     # . epilogue
 9284     5d/pop-to-ebp
 9285     c3/return
 9286 
 9287 test-index-with-non-array-compound-base-type:
 9288     # . prologue
 9289     55/push-ebp
 9290     89/<- %ebp 4/r32/esp
 9291     # setup
 9292     (clear-stream _test-input-stream)
 9293     (clear-stream $_test-input-buffered-file->buffer)
 9294     (clear-stream _test-output-stream)
 9295     (clear-stream $_test-output-buffered-file->buffer)
 9296     (clear-stream _test-error-stream)
 9297     (clear-stream $_test-error-buffered-file->buffer)
 9298     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9299     68/push 0/imm32
 9300     68/push 0/imm32
 9301     89/<- %edx 4/r32/esp
 9302     (tailor-exit-descriptor %edx 0x10)
 9303     #
 9304     (write _test-input-stream "fn foo {\n")
 9305     (write _test-input-stream "  var a: (handle int)\n")
 9306     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9307     (write _test-input-stream "}\n")
 9308     # convert
 9309     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9310     # registers except esp clobbered at this point
 9311     # restore ed
 9312     89/<- %edx 4/r32/esp
 9313     (flush _test-output-buffered-file)
 9314     (flush _test-error-buffered-file)
 9315 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9321     # check output
 9322     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 9323     (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")
 9324     # check that stop(1) was called
 9325     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 9326     # don't restore from ebp
 9327     81 0/subop/add %esp 8/imm32
 9328     # . epilogue
 9329     5d/pop-to-ebp
 9330     c3/return
 9331 
 9332 test-index-with-non-array-compound-base-type-2:
 9333     # . prologue
 9334     55/push-ebp
 9335     89/<- %ebp 4/r32/esp
 9336     # setup
 9337     (clear-stream _test-input-stream)
 9338     (clear-stream $_test-input-buffered-file->buffer)
 9339     (clear-stream _test-output-stream)
 9340     (clear-stream $_test-output-buffered-file->buffer)
 9341     (clear-stream _test-error-stream)
 9342     (clear-stream $_test-error-buffered-file->buffer)
 9343     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9344     68/push 0/imm32
 9345     68/push 0/imm32
 9346     89/<- %edx 4/r32/esp
 9347     (tailor-exit-descriptor %edx 0x10)
 9348     #
 9349     (write _test-input-stream "fn foo {\n")
 9350     (write _test-input-stream "  var a: (addr int)\n")
 9351     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9352     (write _test-input-stream "}\n")
 9353     # convert
 9354     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9355     # registers except esp clobbered at this point
 9356     # restore ed
 9357     89/<- %edx 4/r32/esp
 9358     (flush _test-output-buffered-file)
 9359     (flush _test-error-buffered-file)
 9360 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9366     # check output
 9367     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 9368     (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")
 9369     # check that stop(1) was called
 9370     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 9371     # don't restore from ebp
 9372     81 0/subop/add %esp 8/imm32
 9373     # . epilogue
 9374     5d/pop-to-ebp
 9375     c3/return
 9376 
 9377 test-index-with-array-atom-base-type:
 9378     # . prologue
 9379     55/push-ebp
 9380     89/<- %ebp 4/r32/esp
 9381     # setup
 9382     (clear-stream _test-input-stream)
 9383     (clear-stream $_test-input-buffered-file->buffer)
 9384     (clear-stream _test-output-stream)
 9385     (clear-stream $_test-output-buffered-file->buffer)
 9386     (clear-stream _test-error-stream)
 9387     (clear-stream $_test-error-buffered-file->buffer)
 9388     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9389     68/push 0/imm32
 9390     68/push 0/imm32
 9391     89/<- %edx 4/r32/esp
 9392     (tailor-exit-descriptor %edx 0x10)
 9393     #
 9394     (write _test-input-stream "fn foo {\n")
 9395     (write _test-input-stream "  var a: array\n")
 9396     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9397     (write _test-input-stream "}\n")
 9398     # convert
 9399     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9400     # registers except esp clobbered at this point
 9401     # restore ed
 9402     89/<- %edx 4/r32/esp
 9403     (flush _test-output-buffered-file)
 9404     (flush _test-error-buffered-file)
 9405 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9411     # check output
 9412     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 9413     (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")
 9414     # check that stop(1) was called
 9415     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 9416     # don't restore from ebp
 9417     81 0/subop/add %esp 8/imm32
 9418     # . epilogue
 9419     5d/pop-to-ebp
 9420     c3/return
 9421 
 9422 test-index-with-addr-base-on-stack:
 9423     # . prologue
 9424     55/push-ebp
 9425     89/<- %ebp 4/r32/esp
 9426     # setup
 9427     (clear-stream _test-input-stream)
 9428     (clear-stream $_test-input-buffered-file->buffer)
 9429     (clear-stream _test-output-stream)
 9430     (clear-stream $_test-output-buffered-file->buffer)
 9431     (clear-stream _test-error-stream)
 9432     (clear-stream $_test-error-buffered-file->buffer)
 9433     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9434     68/push 0/imm32
 9435     68/push 0/imm32
 9436     89/<- %edx 4/r32/esp
 9437     (tailor-exit-descriptor %edx 0x10)
 9438     #
 9439     (write _test-input-stream "fn foo {\n")
 9440     (write _test-input-stream "  var a: (addr array int)\n")
 9441     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9442     (write _test-input-stream "}\n")
 9443     # convert
 9444     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9445     # registers except esp clobbered at this point
 9446     # restore ed
 9447     89/<- %edx 4/r32/esp
 9448     (flush _test-output-buffered-file)
 9449     (flush _test-error-buffered-file)
 9450 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9456     # check output
 9457     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
 9458     (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")
 9459     # check that stop(1) was called
 9460     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
 9461     # don't restore from ebp
 9462     81 0/subop/add %esp 8/imm32
 9463     # . epilogue
 9464     5d/pop-to-ebp
 9465     c3/return
 9466 
 9467 test-index-with-wrong-index-type:
 9468     # . prologue
 9469     55/push-ebp
 9470     89/<- %ebp 4/r32/esp
 9471     # setup
 9472     (clear-stream _test-input-stream)
 9473     (clear-stream $_test-input-buffered-file->buffer)
 9474     (clear-stream _test-output-stream)
 9475     (clear-stream $_test-output-buffered-file->buffer)
 9476     (clear-stream _test-error-stream)
 9477     (clear-stream $_test-error-buffered-file->buffer)
 9478     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9479     68/push 0/imm32
 9480     68/push 0/imm32
 9481     89/<- %edx 4/r32/esp
 9482     (tailor-exit-descriptor %edx 0x10)
 9483     #
 9484     (write _test-input-stream "fn foo {\n")
 9485     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9486     (write _test-input-stream "  var b: boolean\n")
 9487     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9488     (write _test-input-stream "}\n")
 9489     # convert
 9490     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9491     # registers except esp clobbered at this point
 9492     # restore ed
 9493     89/<- %edx 4/r32/esp
 9494     (flush _test-output-buffered-file)
 9495     (flush _test-error-buffered-file)
 9496 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9502     # check output
 9503     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
 9504     (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")
 9505     # check that stop(1) was called
 9506     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
 9507     # don't restore from ebp
 9508     81 0/subop/add %esp 8/imm32
 9509     # . epilogue
 9510     5d/pop-to-ebp
 9511     c3/return
 9512 
 9513 test-index-with-offset-atom-index-type:
 9514     # . prologue
 9515     55/push-ebp
 9516     89/<- %ebp 4/r32/esp
 9517     # setup
 9518     (clear-stream _test-input-stream)
 9519     (clear-stream $_test-input-buffered-file->buffer)
 9520     (clear-stream _test-output-stream)
 9521     (clear-stream $_test-output-buffered-file->buffer)
 9522     (clear-stream _test-error-stream)
 9523     (clear-stream $_test-error-buffered-file->buffer)
 9524     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9525     68/push 0/imm32
 9526     68/push 0/imm32
 9527     89/<- %edx 4/r32/esp
 9528     (tailor-exit-descriptor %edx 0x10)
 9529     #
 9530     (write _test-input-stream "fn foo {\n")
 9531     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9532     (write _test-input-stream "  var b: offset\n")
 9533     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9534     (write _test-input-stream "}\n")
 9535     # convert
 9536     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9537     # registers except esp clobbered at this point
 9538     # restore ed
 9539     89/<- %edx 4/r32/esp
 9540     (flush _test-output-buffered-file)
 9541     (flush _test-error-buffered-file)
 9542 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9548     # check output
 9549     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
 9550     (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")
 9551     # check that stop(1) was called
 9552     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
 9553     # don't restore from ebp
 9554     81 0/subop/add %esp 8/imm32
 9555     # . epilogue
 9556     5d/pop-to-ebp
 9557     c3/return
 9558 
 9559 test-index-with-offset-on-stack:
 9560     # . prologue
 9561     55/push-ebp
 9562     89/<- %ebp 4/r32/esp
 9563     # setup
 9564     (clear-stream _test-input-stream)
 9565     (clear-stream $_test-input-buffered-file->buffer)
 9566     (clear-stream _test-output-stream)
 9567     (clear-stream $_test-output-buffered-file->buffer)
 9568     (clear-stream _test-error-stream)
 9569     (clear-stream $_test-error-buffered-file->buffer)
 9570     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9571     68/push 0/imm32
 9572     68/push 0/imm32
 9573     89/<- %edx 4/r32/esp
 9574     (tailor-exit-descriptor %edx 0x10)
 9575     #
 9576     (write _test-input-stream "fn foo {\n")
 9577     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 9578     (write _test-input-stream "  var b: int\n")
 9579     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9580     (write _test-input-stream "}\n")
 9581     # convert
 9582     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9583     # registers except esp clobbered at this point
 9584     # restore ed
 9585     89/<- %edx 4/r32/esp
 9586     (flush _test-output-buffered-file)
 9587     (flush _test-error-buffered-file)
 9588 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9594     # check output
 9595     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
 9596     (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")
 9597     # check that stop(1) was called
 9598     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
 9599     # don't restore from ebp
 9600     81 0/subop/add %esp 8/imm32
 9601     # . epilogue
 9602     5d/pop-to-ebp
 9603     c3/return
 9604 
 9605 test-index-needs-offset-type:
 9606     # . prologue
 9607     55/push-ebp
 9608     89/<- %ebp 4/r32/esp
 9609     # setup
 9610     (clear-stream _test-input-stream)
 9611     (clear-stream $_test-input-buffered-file->buffer)
 9612     (clear-stream _test-output-stream)
 9613     (clear-stream $_test-output-buffered-file->buffer)
 9614     (clear-stream _test-error-stream)
 9615     (clear-stream $_test-error-buffered-file->buffer)
 9616     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9617     68/push 0/imm32
 9618     68/push 0/imm32
 9619     89/<- %edx 4/r32/esp
 9620     (tailor-exit-descriptor %edx 0x10)
 9621     #
 9622     (write _test-input-stream "fn foo {\n")
 9623     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
 9624     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 9625     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 9626     (write _test-input-stream "}\n")
 9627     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
 9628     (write _test-input-stream "  x: int\n")
 9629     (write _test-input-stream "  y: int\n")
 9630     (write _test-input-stream "  z: int\n")
 9631     (write _test-input-stream "}\n")
 9632     # convert
 9633     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9634     # registers except esp clobbered at this point
 9635     # restore ed
 9636     89/<- %edx 4/r32/esp
 9637     (flush _test-output-buffered-file)
 9638     (flush _test-error-buffered-file)
 9639 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9645     # check output
 9646     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
 9647     (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")
 9648     # check that stop(1) was called
 9649     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
 9650     # don't restore from ebp
 9651     81 0/subop/add %esp 8/imm32
 9652     # . epilogue
 9653     5d/pop-to-ebp
 9654     c3/return
 9655 
 9656 test-index-with-output-not-address:
 9657     # . prologue
 9658     55/push-ebp
 9659     89/<- %ebp 4/r32/esp
 9660     # setup
 9661     (clear-stream _test-input-stream)
 9662     (clear-stream $_test-input-buffered-file->buffer)
 9663     (clear-stream _test-output-stream)
 9664     (clear-stream $_test-output-buffered-file->buffer)
 9665     (clear-stream _test-error-stream)
 9666     (clear-stream $_test-error-buffered-file->buffer)
 9667     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9668     68/push 0/imm32
 9669     68/push 0/imm32
 9670     89/<- %edx 4/r32/esp
 9671     (tailor-exit-descriptor %edx 0x10)
 9672     #
 9673     (write _test-input-stream "fn foo {\n")
 9674     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9675     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
 9676     (write _test-input-stream "}\n")
 9677     # convert
 9678     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9679     # registers except esp clobbered at this point
 9680     # restore ed
 9681     89/<- %edx 4/r32/esp
 9682     (flush _test-output-buffered-file)
 9683     (flush _test-error-buffered-file)
 9684 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9690     # check output
 9691     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
 9692     (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")
 9693     # check that stop(1) was called
 9694     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
 9695     # don't restore from ebp
 9696     81 0/subop/add %esp 8/imm32
 9697     # . epilogue
 9698     5d/pop-to-ebp
 9699     c3/return
 9700 
 9701 test-index-with-output-not-address-2:
 9702     # . prologue
 9703     55/push-ebp
 9704     89/<- %ebp 4/r32/esp
 9705     # setup
 9706     (clear-stream _test-input-stream)
 9707     (clear-stream $_test-input-buffered-file->buffer)
 9708     (clear-stream _test-output-stream)
 9709     (clear-stream $_test-output-buffered-file->buffer)
 9710     (clear-stream _test-error-stream)
 9711     (clear-stream $_test-error-buffered-file->buffer)
 9712     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9713     68/push 0/imm32
 9714     68/push 0/imm32
 9715     89/<- %edx 4/r32/esp
 9716     (tailor-exit-descriptor %edx 0x10)
 9717     #
 9718     (write _test-input-stream "fn foo {\n")
 9719     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9720     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
 9721     (write _test-input-stream "}\n")
 9722     # convert
 9723     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9724     # registers except esp clobbered at this point
 9725     # restore ed
 9726     89/<- %edx 4/r32/esp
 9727     (flush _test-output-buffered-file)
 9728     (flush _test-error-buffered-file)
 9729 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9735     # check output
 9736     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
 9737     (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")
 9738     # check that stop(1) was called
 9739     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
 9740     # don't restore from ebp
 9741     81 0/subop/add %esp 8/imm32
 9742     # . epilogue
 9743     5d/pop-to-ebp
 9744     c3/return
 9745 
 9746 test-index-with-wrong-output-type:
 9747     # . prologue
 9748     55/push-ebp
 9749     89/<- %ebp 4/r32/esp
 9750     # setup
 9751     (clear-stream _test-input-stream)
 9752     (clear-stream $_test-input-buffered-file->buffer)
 9753     (clear-stream _test-output-stream)
 9754     (clear-stream $_test-output-buffered-file->buffer)
 9755     (clear-stream _test-error-stream)
 9756     (clear-stream $_test-error-buffered-file->buffer)
 9757     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9758     68/push 0/imm32
 9759     68/push 0/imm32
 9760     89/<- %edx 4/r32/esp
 9761     (tailor-exit-descriptor %edx 0x10)
 9762     #
 9763     (write _test-input-stream "fn foo {\n")
 9764     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9765     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
 9766     (write _test-input-stream "}\n")
 9767     # convert
 9768     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9769     # registers except esp clobbered at this point
 9770     # restore ed
 9771     89/<- %edx 4/r32/esp
 9772     (flush _test-output-buffered-file)
 9773     (flush _test-error-buffered-file)
 9774 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9780     # check output
 9781     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
 9782     (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")
 9783     # check that stop(1) was called
 9784     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
 9785     # don't restore from ebp
 9786     81 0/subop/add %esp 8/imm32
 9787     # . epilogue
 9788     5d/pop-to-ebp
 9789     c3/return
 9790 
 9791 test-index-with-wrong-output-compound-type:
 9792     # . prologue
 9793     55/push-ebp
 9794     89/<- %ebp 4/r32/esp
 9795     # setup
 9796     (clear-stream _test-input-stream)
 9797     (clear-stream $_test-input-buffered-file->buffer)
 9798     (clear-stream _test-output-stream)
 9799     (clear-stream $_test-output-buffered-file->buffer)
 9800     (clear-stream _test-error-stream)
 9801     (clear-stream $_test-error-buffered-file->buffer)
 9802     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9803     68/push 0/imm32
 9804     68/push 0/imm32
 9805     89/<- %edx 4/r32/esp
 9806     (tailor-exit-descriptor %edx 0x10)
 9807     #
 9808     (write _test-input-stream "fn foo {\n")
 9809     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 9810     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
 9811     (write _test-input-stream "}\n")
 9812     # convert
 9813     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9814     # registers except esp clobbered at this point
 9815     # restore ed
 9816     89/<- %edx 4/r32/esp
 9817     (flush _test-output-buffered-file)
 9818     (flush _test-error-buffered-file)
 9819 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9825     # check output
 9826     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
 9827     (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")
 9828     # check that stop(1) was called
 9829     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
 9830     # don't restore from ebp
 9831     81 0/subop/add %esp 8/imm32
 9832     # . epilogue
 9833     5d/pop-to-ebp
 9834     c3/return
 9835 
 9836 test-index-with-no-inouts:
 9837     # . prologue
 9838     55/push-ebp
 9839     89/<- %ebp 4/r32/esp
 9840     # setup
 9841     (clear-stream _test-input-stream)
 9842     (clear-stream $_test-input-buffered-file->buffer)
 9843     (clear-stream _test-output-stream)
 9844     (clear-stream $_test-output-buffered-file->buffer)
 9845     (clear-stream _test-error-stream)
 9846     (clear-stream $_test-error-buffered-file->buffer)
 9847     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9848     68/push 0/imm32
 9849     68/push 0/imm32
 9850     89/<- %edx 4/r32/esp
 9851     (tailor-exit-descriptor %edx 0x10)
 9852     #
 9853     (write _test-input-stream "fn foo {\n")
 9854     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
 9855     (write _test-input-stream "}\n")
 9856     # convert
 9857     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9858     # registers except esp clobbered at this point
 9859     # restore ed
 9860     89/<- %edx 4/r32/esp
 9861     (flush _test-output-buffered-file)
 9862     (flush _test-error-buffered-file)
 9863 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9869     # check output
 9870     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
 9871     (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")
 9872     # check that stop(1) was called
 9873     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
 9874     # don't restore from ebp
 9875     81 0/subop/add %esp 8/imm32
 9876     # . epilogue
 9877     5d/pop-to-ebp
 9878     c3/return
 9879 
 9880 test-index-with-too-few-inouts:
 9881     # . prologue
 9882     55/push-ebp
 9883     89/<- %ebp 4/r32/esp
 9884     # setup
 9885     (clear-stream _test-input-stream)
 9886     (clear-stream $_test-input-buffered-file->buffer)
 9887     (clear-stream _test-output-stream)
 9888     (clear-stream $_test-output-buffered-file->buffer)
 9889     (clear-stream _test-error-stream)
 9890     (clear-stream $_test-error-buffered-file->buffer)
 9891     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9892     68/push 0/imm32
 9893     68/push 0/imm32
 9894     89/<- %edx 4/r32/esp
 9895     (tailor-exit-descriptor %edx 0x10)
 9896     #
 9897     (write _test-input-stream "fn foo {\n")
 9898     (write _test-input-stream "  var a: (array int 3)\n")
 9899     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
 9900     (write _test-input-stream "}\n")
 9901     # convert
 9902     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9903     # registers except esp clobbered at this point
 9904     # restore ed
 9905     89/<- %edx 4/r32/esp
 9906     (flush _test-output-buffered-file)
 9907     (flush _test-error-buffered-file)
 9908 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9914     # check output
 9915     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
 9916     (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")
 9917     # check that stop(1) was called
 9918     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
 9919     # don't restore from ebp
 9920     81 0/subop/add %esp 8/imm32
 9921     # . epilogue
 9922     5d/pop-to-ebp
 9923     c3/return
 9924 
 9925 test-index-with-too-many-inouts:
 9926     # . prologue
 9927     55/push-ebp
 9928     89/<- %ebp 4/r32/esp
 9929     # setup
 9930     (clear-stream _test-input-stream)
 9931     (clear-stream $_test-input-buffered-file->buffer)
 9932     (clear-stream _test-output-stream)
 9933     (clear-stream $_test-output-buffered-file->buffer)
 9934     (clear-stream _test-error-stream)
 9935     (clear-stream $_test-error-buffered-file->buffer)
 9936     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9937     68/push 0/imm32
 9938     68/push 0/imm32
 9939     89/<- %edx 4/r32/esp
 9940     (tailor-exit-descriptor %edx 0x10)
 9941     #
 9942     (write _test-input-stream "fn foo {\n")
 9943     (write _test-input-stream "  var a: (array int 3)\n")
 9944     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
 9945     (write _test-input-stream "}\n")
 9946     # convert
 9947     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9948     # registers except esp clobbered at this point
 9949     # restore ed
 9950     89/<- %edx 4/r32/esp
 9951     (flush _test-output-buffered-file)
 9952     (flush _test-error-buffered-file)
 9953 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9959     # check output
 9960     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
 9961     (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")
 9962     # check that stop(1) was called
 9963     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
 9964     # don't restore from ebp
 9965     81 0/subop/add %esp 8/imm32
 9966     # . epilogue
 9967     5d/pop-to-ebp
 9968     c3/return
 9969 
 9970 test-index-with-no-output:
 9971     # . prologue
 9972     55/push-ebp
 9973     89/<- %ebp 4/r32/esp
 9974     # setup
 9975     (clear-stream _test-input-stream)
 9976     (clear-stream $_test-input-buffered-file->buffer)
 9977     (clear-stream _test-output-stream)
 9978     (clear-stream $_test-output-buffered-file->buffer)
 9979     (clear-stream _test-error-stream)
 9980     (clear-stream $_test-error-buffered-file->buffer)
 9981     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9982     68/push 0/imm32
 9983     68/push 0/imm32
 9984     89/<- %edx 4/r32/esp
 9985     (tailor-exit-descriptor %edx 0x10)
 9986     #
 9987     (write _test-input-stream "fn foo {\n")
 9988     (write _test-input-stream "  var a: (array int 3)\n")
 9989     (write _test-input-stream "  index a, 0\n")
 9990     (write _test-input-stream "}\n")
 9991     # convert
 9992     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9993     # registers except esp clobbered at this point
 9994     # restore ed
 9995     89/<- %edx 4/r32/esp
 9996     (flush _test-output-buffered-file)
 9997     (flush _test-error-buffered-file)
 9998 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10004     # check output
10005     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
10006     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
10007     # check that stop(1) was called
10008     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
10009     # don't restore from ebp
10010     81 0/subop/add %esp 8/imm32
10011     # . epilogue
10012     5d/pop-to-ebp
10013     c3/return
10014 
10015 test-index-with-too-many-outputs:
10016     # . prologue
10017     55/push-ebp
10018     89/<- %ebp 4/r32/esp
10019     # setup
10020     (clear-stream _test-input-stream)
10021     (clear-stream $_test-input-buffered-file->buffer)
10022     (clear-stream _test-output-stream)
10023     (clear-stream $_test-output-buffered-file->buffer)
10024     (clear-stream _test-error-stream)
10025     (clear-stream $_test-error-buffered-file->buffer)
10026     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10027     68/push 0/imm32
10028     68/push 0/imm32
10029     89/<- %edx 4/r32/esp
10030     (tailor-exit-descriptor %edx 0x10)
10031     #
10032     (write _test-input-stream "fn foo {\n")
10033     (write _test-input-stream "  var a: (array int 3)\n")
10034     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
10035     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
10036     (write _test-input-stream "  b, c <- index a, 0\n")
10037     (write _test-input-stream "}\n")
10038     # convert
10039     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10040     # registers except esp clobbered at this point
10041     # restore ed
10042     89/<- %edx 4/r32/esp
10043     (flush _test-output-buffered-file)
10044     (flush _test-error-buffered-file)
10045 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10051     # check output
10052     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
10053     (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")
10054     # check that stop(1) was called
10055     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
10056     # don't restore from ebp
10057     81 0/subop/add %esp 8/imm32
10058     # . epilogue
10059     5d/pop-to-ebp
10060     c3/return
10061 
10062 test-compute-offset-with-non-array-atom-base-type:
10063     # . prologue
10064     55/push-ebp
10065     89/<- %ebp 4/r32/esp
10066     # setup
10067     (clear-stream _test-input-stream)
10068     (clear-stream $_test-input-buffered-file->buffer)
10069     (clear-stream _test-output-stream)
10070     (clear-stream $_test-output-buffered-file->buffer)
10071     (clear-stream _test-error-stream)
10072     (clear-stream $_test-error-buffered-file->buffer)
10073     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10074     68/push 0/imm32
10075     68/push 0/imm32
10076     89/<- %edx 4/r32/esp
10077     (tailor-exit-descriptor %edx 0x10)
10078     #
10079     (write _test-input-stream "fn foo {\n")
10080     (write _test-input-stream "  var a: int\n")
10081     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10082     (write _test-input-stream "}\n")
10083     # convert
10084     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10085     # registers except esp clobbered at this point
10086     # restore ed
10087     89/<- %edx 4/r32/esp
10088     (flush _test-output-buffered-file)
10089     (flush _test-error-buffered-file)
10090 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10096     # check output
10097     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
10098     (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")
10099     # check that stop(1) was called
10100     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
10101     # don't restore from ebp
10102     81 0/subop/add %esp 8/imm32
10103     # . epilogue
10104     5d/pop-to-ebp
10105     c3/return
10106 
10107 test-compute-offset-with-non-array-compound-base-type:
10108     # . prologue
10109     55/push-ebp
10110     89/<- %ebp 4/r32/esp
10111     # setup
10112     (clear-stream _test-input-stream)
10113     (clear-stream $_test-input-buffered-file->buffer)
10114     (clear-stream _test-output-stream)
10115     (clear-stream $_test-output-buffered-file->buffer)
10116     (clear-stream _test-error-stream)
10117     (clear-stream $_test-error-buffered-file->buffer)
10118     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10119     68/push 0/imm32
10120     68/push 0/imm32
10121     89/<- %edx 4/r32/esp
10122     (tailor-exit-descriptor %edx 0x10)
10123     #
10124     (write _test-input-stream "fn foo {\n")
10125     (write _test-input-stream "  var a: (handle int)\n")
10126     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10127     (write _test-input-stream "}\n")
10128     # convert
10129     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10130     # registers except esp clobbered at this point
10131     # restore ed
10132     89/<- %edx 4/r32/esp
10133     (flush _test-output-buffered-file)
10134     (flush _test-error-buffered-file)
10135 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10141     # check output
10142     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
10143     (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")
10144     # check that stop(1) was called
10145     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
10146     # don't restore from ebp
10147     81 0/subop/add %esp 8/imm32
10148     # . epilogue
10149     5d/pop-to-ebp
10150     c3/return
10151 
10152 test-compute-offset-with-non-array-compound-base-type-2:
10153     # . prologue
10154     55/push-ebp
10155     89/<- %ebp 4/r32/esp
10156     # setup
10157     (clear-stream _test-input-stream)
10158     (clear-stream $_test-input-buffered-file->buffer)
10159     (clear-stream _test-output-stream)
10160     (clear-stream $_test-output-buffered-file->buffer)
10161     (clear-stream _test-error-stream)
10162     (clear-stream $_test-error-buffered-file->buffer)
10163     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10164     68/push 0/imm32
10165     68/push 0/imm32
10166     89/<- %edx 4/r32/esp
10167     (tailor-exit-descriptor %edx 0x10)
10168     #
10169     (write _test-input-stream "fn foo {\n")
10170     (write _test-input-stream "  var a: (addr int)\n")
10171     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10172     (write _test-input-stream "}\n")
10173     # convert
10174     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10175     # registers except esp clobbered at this point
10176     # restore ed
10177     89/<- %edx 4/r32/esp
10178     (flush _test-output-buffered-file)
10179     (flush _test-error-buffered-file)
10180 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10186     # check output
10187     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
10188     (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")
10189     # check that stop(1) was called
10190     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
10191     # don't restore from ebp
10192     81 0/subop/add %esp 8/imm32
10193     # . epilogue
10194     5d/pop-to-ebp
10195     c3/return
10196 
10197 test-compute-offset-with-array-atom-base-type:
10198     # . prologue
10199     55/push-ebp
10200     89/<- %ebp 4/r32/esp
10201     # setup
10202     (clear-stream _test-input-stream)
10203     (clear-stream $_test-input-buffered-file->buffer)
10204     (clear-stream _test-output-stream)
10205     (clear-stream $_test-output-buffered-file->buffer)
10206     (clear-stream _test-error-stream)
10207     (clear-stream $_test-error-buffered-file->buffer)
10208     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10209     68/push 0/imm32
10210     68/push 0/imm32
10211     89/<- %edx 4/r32/esp
10212     (tailor-exit-descriptor %edx 0x10)
10213     #
10214     (write _test-input-stream "fn foo {\n")
10215     (write _test-input-stream "  var a: array\n")
10216     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10217     (write _test-input-stream "}\n")
10218     # convert
10219     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10220     # registers except esp clobbered at this point
10221     # restore ed
10222     89/<- %edx 4/r32/esp
10223     (flush _test-output-buffered-file)
10224     (flush _test-error-buffered-file)
10225 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10231     # check output
10232     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
10233     (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")
10234     # check that stop(1) was called
10235     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
10236     # don't restore from ebp
10237     81 0/subop/add %esp 8/imm32
10238     # . epilogue
10239     5d/pop-to-ebp
10240     c3/return
10241 
10242 test-compute-offset-with-wrong-index-type:
10243     # . prologue
10244     55/push-ebp
10245     89/<- %ebp 4/r32/esp
10246     # setup
10247     (clear-stream _test-input-stream)
10248     (clear-stream $_test-input-buffered-file->buffer)
10249     (clear-stream _test-output-stream)
10250     (clear-stream $_test-output-buffered-file->buffer)
10251     (clear-stream _test-error-stream)
10252     (clear-stream $_test-error-buffered-file->buffer)
10253     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10254     68/push 0/imm32
10255     68/push 0/imm32
10256     89/<- %edx 4/r32/esp
10257     (tailor-exit-descriptor %edx 0x10)
10258     #
10259     (write _test-input-stream "fn foo {\n")
10260     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10261     (write _test-input-stream "  var b: boolean\n")
10262     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
10263     (write _test-input-stream "}\n")
10264     # convert
10265     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10266     # registers except esp clobbered at this point
10267     # restore ed
10268     89/<- %edx 4/r32/esp
10269     (flush _test-output-buffered-file)
10270     (flush _test-error-buffered-file)
10271 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10277     # check output
10278     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
10279     (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")
10280     # check that stop(1) was called
10281     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
10282     # don't restore from ebp
10283     81 0/subop/add %esp 8/imm32
10284     # . epilogue
10285     5d/pop-to-ebp
10286     c3/return
10287 
10288 test-compute-offset-with-output-not-offset:
10289     # . prologue
10290     55/push-ebp
10291     89/<- %ebp 4/r32/esp
10292     # setup
10293     (clear-stream _test-input-stream)
10294     (clear-stream $_test-input-buffered-file->buffer)
10295     (clear-stream _test-output-stream)
10296     (clear-stream $_test-output-buffered-file->buffer)
10297     (clear-stream _test-error-stream)
10298     (clear-stream $_test-error-buffered-file->buffer)
10299     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10300     68/push 0/imm32
10301     68/push 0/imm32
10302     89/<- %edx 4/r32/esp
10303     (tailor-exit-descriptor %edx 0x10)
10304     #
10305     (write _test-input-stream "fn foo {\n")
10306     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10307     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
10308     (write _test-input-stream "}\n")
10309     # convert
10310     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10311     # registers except esp clobbered at this point
10312     # restore ed
10313     89/<- %edx 4/r32/esp
10314     (flush _test-output-buffered-file)
10315     (flush _test-error-buffered-file)
10316 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10322     # check output
10323     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
10324     (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")
10325     # check that stop(1) was called
10326     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
10327     # don't restore from ebp
10328     81 0/subop/add %esp 8/imm32
10329     # . epilogue
10330     5d/pop-to-ebp
10331     c3/return
10332 
10333 test-compute-offset-with-output-not-address-2:
10334     # . prologue
10335     55/push-ebp
10336     89/<- %ebp 4/r32/esp
10337     # setup
10338     (clear-stream _test-input-stream)
10339     (clear-stream $_test-input-buffered-file->buffer)
10340     (clear-stream _test-output-stream)
10341     (clear-stream $_test-output-buffered-file->buffer)
10342     (clear-stream _test-error-stream)
10343     (clear-stream $_test-error-buffered-file->buffer)
10344     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10345     68/push 0/imm32
10346     68/push 0/imm32
10347     89/<- %edx 4/r32/esp
10348     (tailor-exit-descriptor %edx 0x10)
10349     #
10350     (write _test-input-stream "fn foo {\n")
10351     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10352     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
10353     (write _test-input-stream "}\n")
10354     # convert
10355     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10356     # registers except esp clobbered at this point
10357     # restore ed
10358     89/<- %edx 4/r32/esp
10359     (flush _test-output-buffered-file)
10360     (flush _test-error-buffered-file)
10361 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10367     # check output
10368     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
10369     (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")
10370     # check that stop(1) was called
10371     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
10372     # don't restore from ebp
10373     81 0/subop/add %esp 8/imm32
10374     # . epilogue
10375     5d/pop-to-ebp
10376     c3/return
10377 
10378 test-compute-offset-with-wrong-output-type:
10379     # . prologue
10380     55/push-ebp
10381     89/<- %ebp 4/r32/esp
10382     # setup
10383     (clear-stream _test-input-stream)
10384     (clear-stream $_test-input-buffered-file->buffer)
10385     (clear-stream _test-output-stream)
10386     (clear-stream $_test-output-buffered-file->buffer)
10387     (clear-stream _test-error-stream)
10388     (clear-stream $_test-error-buffered-file->buffer)
10389     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10390     68/push 0/imm32
10391     68/push 0/imm32
10392     89/<- %edx 4/r32/esp
10393     (tailor-exit-descriptor %edx 0x10)
10394     #
10395     (write _test-input-stream "fn foo {\n")
10396     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10397     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
10398     (write _test-input-stream "}\n")
10399     # convert
10400     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10401     # registers except esp clobbered at this point
10402     # restore ed
10403     89/<- %edx 4/r32/esp
10404     (flush _test-output-buffered-file)
10405     (flush _test-error-buffered-file)
10406 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10412     # check output
10413     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
10414     (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")
10415     # check that stop(1) was called
10416     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
10417     # don't restore from ebp
10418     81 0/subop/add %esp 8/imm32
10419     # . epilogue
10420     5d/pop-to-ebp
10421     c3/return
10422 
10423 test-compute-offset-with-wrong-output-compound-type:
10424     # . prologue
10425     55/push-ebp
10426     89/<- %ebp 4/r32/esp
10427     # setup
10428     (clear-stream _test-input-stream)
10429     (clear-stream $_test-input-buffered-file->buffer)
10430     (clear-stream _test-output-stream)
10431     (clear-stream $_test-output-buffered-file->buffer)
10432     (clear-stream _test-error-stream)
10433     (clear-stream $_test-error-buffered-file->buffer)
10434     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10435     68/push 0/imm32
10436     68/push 0/imm32
10437     89/<- %edx 4/r32/esp
10438     (tailor-exit-descriptor %edx 0x10)
10439     #
10440     (write _test-input-stream "fn foo {\n")
10441     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
10442     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
10443     (write _test-input-stream "}\n")
10444     # convert
10445     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10446     # registers except esp clobbered at this point
10447     # restore ed
10448     89/<- %edx 4/r32/esp
10449     (flush _test-output-buffered-file)
10450     (flush _test-error-buffered-file)
10451 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10457     # check output
10458     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
10459     (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")
10460     # check that stop(1) was called
10461     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
10462     # don't restore from ebp
10463     81 0/subop/add %esp 8/imm32
10464     # . epilogue
10465     5d/pop-to-ebp
10466     c3/return
10467 
10468 test-compute-offset-with-no-inouts:
10469     # . prologue
10470     55/push-ebp
10471     89/<- %ebp 4/r32/esp
10472     # setup
10473     (clear-stream _test-input-stream)
10474     (clear-stream $_test-input-buffered-file->buffer)
10475     (clear-stream _test-output-stream)
10476     (clear-stream $_test-output-buffered-file->buffer)
10477     (clear-stream _test-error-stream)
10478     (clear-stream $_test-error-buffered-file->buffer)
10479     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10480     68/push 0/imm32
10481     68/push 0/imm32
10482     89/<- %edx 4/r32/esp
10483     (tailor-exit-descriptor %edx 0x10)
10484     #
10485     (write _test-input-stream "fn foo {\n")
10486     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
10487     (write _test-input-stream "}\n")
10488     # convert
10489     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10490     # registers except esp clobbered at this point
10491     # restore ed
10492     89/<- %edx 4/r32/esp
10493     (flush _test-output-buffered-file)
10494     (flush _test-error-buffered-file)
10495 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10501     # check output
10502     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
10503     (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")
10504     # check that stop(1) was called
10505     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
10506     # don't restore from ebp
10507     81 0/subop/add %esp 8/imm32
10508     # . epilogue
10509     5d/pop-to-ebp
10510     c3/return
10511 
10512 test-compute-offset-with-too-few-inouts:
10513     # . prologue
10514     55/push-ebp
10515     89/<- %ebp 4/r32/esp
10516     # setup
10517     (clear-stream _test-input-stream)
10518     (clear-stream $_test-input-buffered-file->buffer)
10519     (clear-stream _test-output-stream)
10520     (clear-stream $_test-output-buffered-file->buffer)
10521     (clear-stream _test-error-stream)
10522     (clear-stream $_test-error-buffered-file->buffer)
10523     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10524     68/push 0/imm32
10525     68/push 0/imm32
10526     89/<- %edx 4/r32/esp
10527     (tailor-exit-descriptor %edx 0x10)
10528     #
10529     (write _test-input-stream "fn foo {\n")
10530     (write _test-input-stream "  var a: (array int 3)\n")
10531     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
10532     (write _test-input-stream "}\n")
10533     # convert
10534     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10535     # registers except esp clobbered at this point
10536     # restore ed
10537     89/<- %edx 4/r32/esp
10538     (flush _test-output-buffered-file)
10539     (flush _test-error-buffered-file)
10540 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10546     # check output
10547     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
10548     (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")
10549     # check that stop(1) was called
10550     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
10551     # don't restore from ebp
10552     81 0/subop/add %esp 8/imm32
10553     # . epilogue
10554     5d/pop-to-ebp
10555     c3/return
10556 
10557 test-compute-offset-with-too-many-inouts:
10558     # . prologue
10559     55/push-ebp
10560     89/<- %ebp 4/r32/esp
10561     # setup
10562     (clear-stream _test-input-stream)
10563     (clear-stream $_test-input-buffered-file->buffer)
10564     (clear-stream _test-output-stream)
10565     (clear-stream $_test-output-buffered-file->buffer)
10566     (clear-stream _test-error-stream)
10567     (clear-stream $_test-error-buffered-file->buffer)
10568     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10569     68/push 0/imm32
10570     68/push 0/imm32
10571     89/<- %edx 4/r32/esp
10572     (tailor-exit-descriptor %edx 0x10)
10573     #
10574     (write _test-input-stream "fn foo {\n")
10575     (write _test-input-stream "  var a: (array int 3)\n")
10576     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
10577     (write _test-input-stream "}\n")
10578     # convert
10579     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10580     # registers except esp clobbered at this point
10581     # restore ed
10582     89/<- %edx 4/r32/esp
10583     (flush _test-output-buffered-file)
10584     (flush _test-error-buffered-file)
10585 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10591     # check output
10592     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
10593     (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")
10594     # check that stop(1) was called
10595     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
10596     # don't restore from ebp
10597     81 0/subop/add %esp 8/imm32
10598     # . epilogue
10599     5d/pop-to-ebp
10600     c3/return
10601 
10602 test-compute-offset-with-no-output:
10603     # . prologue
10604     55/push-ebp
10605     89/<- %ebp 4/r32/esp
10606     # setup
10607     (clear-stream _test-input-stream)
10608     (clear-stream $_test-input-buffered-file->buffer)
10609     (clear-stream _test-output-stream)
10610     (clear-stream $_test-output-buffered-file->buffer)
10611     (clear-stream _test-error-stream)
10612     (clear-stream $_test-error-buffered-file->buffer)
10613     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10614     68/push 0/imm32
10615     68/push 0/imm32
10616     89/<- %edx 4/r32/esp
10617     (tailor-exit-descriptor %edx 0x10)
10618     #
10619     (write _test-input-stream "fn foo {\n")
10620     (write _test-input-stream "  var a: (array int 3)\n")
10621     (write _test-input-stream "  compute-offset a, 0\n")
10622     (write _test-input-stream "}\n")
10623     # convert
10624     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10625     # registers except esp clobbered at this point
10626     # restore ed
10627     89/<- %edx 4/r32/esp
10628     (flush _test-output-buffered-file)
10629     (flush _test-error-buffered-file)
10630 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10636     # check output
10637     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
10638     (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")
10639     # check that stop(1) was called
10640     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
10641     # don't restore from ebp
10642     81 0/subop/add %esp 8/imm32
10643     # . epilogue
10644     5d/pop-to-ebp
10645     c3/return
10646 
10647 test-compute-offset-with-too-many-outputs:
10648     # . prologue
10649     55/push-ebp
10650     89/<- %ebp 4/r32/esp
10651     # setup
10652     (clear-stream _test-input-stream)
10653     (clear-stream $_test-input-buffered-file->buffer)
10654     (clear-stream _test-output-stream)
10655     (clear-stream $_test-output-buffered-file->buffer)
10656     (clear-stream _test-error-stream)
10657     (clear-stream $_test-error-buffered-file->buffer)
10658     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10659     68/push 0/imm32
10660     68/push 0/imm32
10661     89/<- %edx 4/r32/esp
10662     (tailor-exit-descriptor %edx 0x10)
10663     #
10664     (write _test-input-stream "fn foo {\n")
10665     (write _test-input-stream "  var a: (array int 3)\n")
10666     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
10667     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
10668     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
10669     (write _test-input-stream "}\n")
10670     # convert
10671     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10672     # registers except esp clobbered at this point
10673     # restore ed
10674     89/<- %edx 4/r32/esp
10675     (flush _test-output-buffered-file)
10676     (flush _test-error-buffered-file)
10677 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10683     # check output
10684     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
10685     (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")
10686     # check that stop(1) was called
10687     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
10688     # don't restore from ebp
10689     81 0/subop/add %esp 8/imm32
10690     # . epilogue
10691     5d/pop-to-ebp
10692     c3/return
10693 
10694 test-convert-read-from-stream:
10695     # . prologue
10696     55/push-ebp
10697     89/<- %ebp 4/r32/esp
10698     # setup
10699     (clear-stream _test-input-stream)
10700     (clear-stream $_test-input-buffered-file->buffer)
10701     (clear-stream _test-output-stream)
10702     (clear-stream $_test-output-buffered-file->buffer)
10703     #
10704     (write _test-input-stream "fn foo {\n")
10705     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
10706     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
10707     (write _test-input-stream "  read-from-stream s, o\n")
10708     (write _test-input-stream "}\n")
10709     # convert
10710     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10711     # registers except esp clobbered at this point
10712     # restore ed
10713     89/<- %edx 4/r32/esp
10714     (flush _test-output-buffered-file)
10715     (flush _test-error-buffered-file)
10716 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
10722     # check output
10723     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
10724     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
10725     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
10726     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
10727     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
10728     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
10729     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
10730     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
10731     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
10732     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
10733     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
10734     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
10735     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
10736     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
10737     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
10738     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
10739     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
10740     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
10741     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
10742     # . epilogue
10743     89/<- %esp 5/r32/ebp
10744     5d/pop-to-ebp
10745     c3/return
10746 
10747 test-convert-read-from-stream-with-correct-payload-size:
10748     # . prologue
10749     55/push-ebp
10750     89/<- %ebp 4/r32/esp
10751     # setup
10752     (clear-stream _test-input-stream)
10753     (clear-stream $_test-input-buffered-file->buffer)
10754     (clear-stream _test-output-stream)
10755     (clear-stream $_test-output-buffered-file->buffer)
10756     #
10757     (write _test-input-stream "fn foo {\n")
10758     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
10759     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
10760     (write _test-input-stream "  read-from-stream s, o\n")
10761     (write _test-input-stream "}\n")
10762     # convert
10763     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10764     # registers except esp clobbered at this point
10765     # restore ed
10766     89/<- %edx 4/r32/esp
10767     (flush _test-output-buffered-file)
10768     (flush _test-error-buffered-file)
10769 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
10775     # check output
10776     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
10777     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
10778     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
10779     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
10780     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
10781     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
10782     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
10783     (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")
10784     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
10785     (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")
10786     (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")
10787     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
10788     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
10789     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
10790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
10791     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
10792     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
10793     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
10794     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
10795     # . epilogue
10796     89/<- %esp 5/r32/ebp
10797     5d/pop-to-ebp
10798     c3/return
10799 
10800 test-read-from-stream-with-non-stream-atom-base-type:
10801     # . prologue
10802     55/push-ebp
10803     89/<- %ebp 4/r32/esp
10804     # setup
10805     (clear-stream _test-input-stream)
10806     (clear-stream $_test-input-buffered-file->buffer)
10807     (clear-stream _test-output-stream)
10808     (clear-stream $_test-output-buffered-file->buffer)
10809     (clear-stream _test-error-stream)
10810     (clear-stream $_test-error-buffered-file->buffer)
10811     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10812     68/push 0/imm32
10813     68/push 0/imm32
10814     89/<- %edx 4/r32/esp
10815     (tailor-exit-descriptor %edx 0x10)
10816     #
10817     (write _test-input-stream "fn foo {\n")
10818     (write _test-input-stream "  var a: int\n")
10819     (write _test-input-stream "  read-from-stream a, 0\n")
10820     (write _test-input-stream "}\n")
10821     # convert
10822     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10823     # registers except esp clobbered at this point
10824     # restore ed
10825     89/<- %edx 4/r32/esp
10826     (flush _test-output-buffered-file)
10827     (flush _test-error-buffered-file)
10828 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10834     # check output
10835     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
10836     (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")
10837     # check that stop(1) was called
10838     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
10839     # don't restore from ebp
10840     81 0/subop/add %esp 8/imm32
10841     # . epilogue
10842     5d/pop-to-ebp
10843     c3/return
10844 
10845 test-read-from-stream-with-non-stream-compound-base-type:
10846     # . prologue
10847     55/push-ebp
10848     89/<- %ebp 4/r32/esp
10849     # setup
10850     (clear-stream _test-input-stream)
10851     (clear-stream $_test-input-buffered-file->buffer)
10852     (clear-stream _test-output-stream)
10853     (clear-stream $_test-output-buffered-file->buffer)
10854     (clear-stream _test-error-stream)
10855     (clear-stream $_test-error-buffered-file->buffer)
10856     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10857     68/push 0/imm32
10858     68/push 0/imm32
10859     89/<- %edx 4/r32/esp
10860     (tailor-exit-descriptor %edx 0x10)
10861     #
10862     (write _test-input-stream "fn foo {\n")
10863     (write _test-input-stream "  var a: (handle int)\n")
10864     (write _test-input-stream "  read-from-stream a, 0\n")
10865     (write _test-input-stream "}\n")
10866     # convert
10867     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10868     # registers except esp clobbered at this point
10869     # restore ed
10870     89/<- %edx 4/r32/esp
10871     (flush _test-output-buffered-file)
10872     (flush _test-error-buffered-file)
10873 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10879     # check output
10880     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
10881     (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")
10882     # check that stop(1) was called
10883     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
10884     # don't restore from ebp
10885     81 0/subop/add %esp 8/imm32
10886     # . epilogue
10887     5d/pop-to-ebp
10888     c3/return
10889 
10890 test-read-from-stream-with-non-stream-compound-base-type-2:
10891     # . prologue
10892     55/push-ebp
10893     89/<- %ebp 4/r32/esp
10894     # setup
10895     (clear-stream _test-input-stream)
10896     (clear-stream $_test-input-buffered-file->buffer)
10897     (clear-stream _test-output-stream)
10898     (clear-stream $_test-output-buffered-file->buffer)
10899     (clear-stream _test-error-stream)
10900     (clear-stream $_test-error-buffered-file->buffer)
10901     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10902     68/push 0/imm32
10903     68/push 0/imm32
10904     89/<- %edx 4/r32/esp
10905     (tailor-exit-descriptor %edx 0x10)
10906     #
10907     (write _test-input-stream "fn foo {\n")
10908     (write _test-input-stream "  var a: (addr int)\n")
10909     (write _test-input-stream "  read-from-stream a, 0\n")
10910     (write _test-input-stream "}\n")
10911     # convert
10912     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10913     # registers except esp clobbered at this point
10914     # restore ed
10915     89/<- %edx 4/r32/esp
10916     (flush _test-output-buffered-file)
10917     (flush _test-error-buffered-file)
10918 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10924     # check output
10925     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
10926     (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")
10927     # check that stop(1) was called
10928     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
10929     # don't restore from ebp
10930     81 0/subop/add %esp 8/imm32
10931     # . epilogue
10932     5d/pop-to-ebp
10933     c3/return
10934 
10935 test-read-from-stream-with-stream-atom-base-type:
10936     # . prologue
10937     55/push-ebp
10938     89/<- %ebp 4/r32/esp
10939     # setup
10940     (clear-stream _test-input-stream)
10941     (clear-stream $_test-input-buffered-file->buffer)
10942     (clear-stream _test-output-stream)
10943     (clear-stream $_test-output-buffered-file->buffer)
10944     (clear-stream _test-error-stream)
10945     (clear-stream $_test-error-buffered-file->buffer)
10946     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10947     68/push 0/imm32
10948     68/push 0/imm32
10949     89/<- %edx 4/r32/esp
10950     (tailor-exit-descriptor %edx 0x10)
10951     #
10952     (write _test-input-stream "fn foo {\n")
10953     (write _test-input-stream "  var a: stream\n")
10954     (write _test-input-stream "  read-from-stream a, 0\n")
10955     (write _test-input-stream "}\n")
10956     # convert
10957     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10958     # registers except esp clobbered at this point
10959     # restore ed
10960     89/<- %edx 4/r32/esp
10961     (flush _test-output-buffered-file)
10962     (flush _test-error-buffered-file)
10963 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10969     # check output
10970     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
10971     (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")
10972     # check that stop(1) was called
10973     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
10974     # don't restore from ebp
10975     81 0/subop/add %esp 8/imm32
10976     # . epilogue
10977     5d/pop-to-ebp
10978     c3/return
10979 
10980 test-read-from-stream-with-wrong-index-type:
10981     # . prologue
10982     55/push-ebp
10983     89/<- %ebp 4/r32/esp
10984     # setup
10985     (clear-stream _test-input-stream)
10986     (clear-stream $_test-input-buffered-file->buffer)
10987     (clear-stream _test-output-stream)
10988     (clear-stream $_test-output-buffered-file->buffer)
10989     (clear-stream _test-error-stream)
10990     (clear-stream $_test-error-buffered-file->buffer)
10991     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10992     68/push 0/imm32
10993     68/push 0/imm32
10994     89/<- %edx 4/r32/esp
10995     (tailor-exit-descriptor %edx 0x10)
10996     #
10997     (write _test-input-stream "fn foo {\n")
10998     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
10999     (write _test-input-stream "  var b: boolean\n")
11000     (write _test-input-stream "  read-from-stream a, b\n")
11001     (write _test-input-stream "}\n")
11002     # convert
11003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11004     # registers except esp clobbered at this point
11005     # restore ed
11006     89/<- %edx 4/r32/esp
11007     (flush _test-output-buffered-file)
11008     (flush _test-error-buffered-file)
11009 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11015     # check output
11016     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
11017     (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")
11018     # check that stop(1) was called
11019     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
11020     # don't restore from ebp
11021     81 0/subop/add %esp 8/imm32
11022     # . epilogue
11023     5d/pop-to-ebp
11024     c3/return
11025 
11026 test-read-from-stream-with-no-inouts:
11027     # . prologue
11028     55/push-ebp
11029     89/<- %ebp 4/r32/esp
11030     # setup
11031     (clear-stream _test-input-stream)
11032     (clear-stream $_test-input-buffered-file->buffer)
11033     (clear-stream _test-output-stream)
11034     (clear-stream $_test-output-buffered-file->buffer)
11035     (clear-stream _test-error-stream)
11036     (clear-stream $_test-error-buffered-file->buffer)
11037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11038     68/push 0/imm32
11039     68/push 0/imm32
11040     89/<- %edx 4/r32/esp
11041     (tailor-exit-descriptor %edx 0x10)
11042     #
11043     (write _test-input-stream "fn foo {\n")
11044     (write _test-input-stream "  read-from-stream\n")
11045     (write _test-input-stream "}\n")
11046     # convert
11047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11048     # registers except esp clobbered at this point
11049     # restore ed
11050     89/<- %edx 4/r32/esp
11051     (flush _test-output-buffered-file)
11052     (flush _test-error-buffered-file)
11053 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11059     # check output
11060     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
11061     (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")
11062     # check that stop(1) was called
11063     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
11064     # don't restore from ebp
11065     81 0/subop/add %esp 8/imm32
11066     # . epilogue
11067     5d/pop-to-ebp
11068     c3/return
11069 
11070 test-read-from-stream-with-too-few-inouts:
11071     # . prologue
11072     55/push-ebp
11073     89/<- %ebp 4/r32/esp
11074     # setup
11075     (clear-stream _test-input-stream)
11076     (clear-stream $_test-input-buffered-file->buffer)
11077     (clear-stream _test-output-stream)
11078     (clear-stream $_test-output-buffered-file->buffer)
11079     (clear-stream _test-error-stream)
11080     (clear-stream $_test-error-buffered-file->buffer)
11081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11082     68/push 0/imm32
11083     68/push 0/imm32
11084     89/<- %edx 4/r32/esp
11085     (tailor-exit-descriptor %edx 0x10)
11086     #
11087     (write _test-input-stream "fn foo {\n")
11088     (write _test-input-stream "  var a: (addr stream int)\n")
11089     (write _test-input-stream "  read-from-stream a\n")
11090     (write _test-input-stream "}\n")
11091     # convert
11092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11093     # registers except esp clobbered at this point
11094     # restore ed
11095     89/<- %edx 4/r32/esp
11096     (flush _test-output-buffered-file)
11097     (flush _test-error-buffered-file)
11098 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11104     # check output
11105     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
11106     (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")
11107     # check that stop(1) was called
11108     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
11109     # don't restore from ebp
11110     81 0/subop/add %esp 8/imm32
11111     # . epilogue
11112     5d/pop-to-ebp
11113     c3/return
11114 
11115 test-read-from-stream-with-too-many-inouts:
11116     # . prologue
11117     55/push-ebp
11118     89/<- %ebp 4/r32/esp
11119     # setup
11120     (clear-stream _test-input-stream)
11121     (clear-stream $_test-input-buffered-file->buffer)
11122     (clear-stream _test-output-stream)
11123     (clear-stream $_test-output-buffered-file->buffer)
11124     (clear-stream _test-error-stream)
11125     (clear-stream $_test-error-buffered-file->buffer)
11126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11127     68/push 0/imm32
11128     68/push 0/imm32
11129     89/<- %edx 4/r32/esp
11130     (tailor-exit-descriptor %edx 0x10)
11131     #
11132     (write _test-input-stream "fn foo {\n")
11133     (write _test-input-stream "  var a: (addr stream int)\n")
11134     (write _test-input-stream "  var b: (addr int)\n")
11135     (write _test-input-stream "  read-from-stream a, b, 0\n")
11136     (write _test-input-stream "}\n")
11137     # convert
11138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11139     # registers except esp clobbered at this point
11140     # restore ed
11141     89/<- %edx 4/r32/esp
11142     (flush _test-output-buffered-file)
11143     (flush _test-error-buffered-file)
11144 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11150     # check output
11151     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
11152     (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")
11153     # check that stop(1) was called
11154     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
11155     # don't restore from ebp
11156     81 0/subop/add %esp 8/imm32
11157     # . epilogue
11158     5d/pop-to-ebp
11159     c3/return
11160 
11161 test-read-from-stream-with-output:
11162     # . prologue
11163     55/push-ebp
11164     89/<- %ebp 4/r32/esp
11165     # setup
11166     (clear-stream _test-input-stream)
11167     (clear-stream $_test-input-buffered-file->buffer)
11168     (clear-stream _test-output-stream)
11169     (clear-stream $_test-output-buffered-file->buffer)
11170     (clear-stream _test-error-stream)
11171     (clear-stream $_test-error-buffered-file->buffer)
11172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11173     68/push 0/imm32
11174     68/push 0/imm32
11175     89/<- %edx 4/r32/esp
11176     (tailor-exit-descriptor %edx 0x10)
11177     #
11178     (write _test-input-stream "fn foo {\n")
11179     (write _test-input-stream "  var a: (addr stream int)\n")
11180     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11181     (write _test-input-stream "  b <- read-from-stream a, b\n")
11182     (write _test-input-stream "}\n")
11183     # convert
11184     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11185     # registers except esp clobbered at this point
11186     # restore ed
11187     89/<- %edx 4/r32/esp
11188     (flush _test-output-buffered-file)
11189     (flush _test-error-buffered-file)
11190 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11196     # check output
11197     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
11198     (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")
11199     # check that stop(1) was called
11200     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
11201     # don't restore from ebp
11202     81 0/subop/add %esp 8/imm32
11203     # . epilogue
11204     5d/pop-to-ebp
11205     c3/return
11206 
11207 test-convert-write-to-stream:
11208     # . prologue
11209     55/push-ebp
11210     89/<- %ebp 4/r32/esp
11211     # setup
11212     (clear-stream _test-input-stream)
11213     (clear-stream $_test-input-buffered-file->buffer)
11214     (clear-stream _test-output-stream)
11215     (clear-stream $_test-output-buffered-file->buffer)
11216     #
11217     (write _test-input-stream "fn foo {\n")
11218     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11219     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11220     (write _test-input-stream "  write-to-stream s, o\n")
11221     (write _test-input-stream "}\n")
11222     # convert
11223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11224     # registers except esp clobbered at this point
11225     # restore ed
11226     89/<- %edx 4/r32/esp
11227     (flush _test-output-buffered-file)
11228     (flush _test-error-buffered-file)
11229 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11235     # check output
11236     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
11237     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
11238     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
11239     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
11240     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
11241     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
11242     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
11243     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
11244     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
11245     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
11246     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
11247     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
11248     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
11249     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
11250     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
11251     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
11252     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
11253     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
11254     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
11255     # . epilogue
11256     89/<- %esp 5/r32/ebp
11257     5d/pop-to-ebp
11258     c3/return
11259 
11260 test-convert-write-to-stream-with-correct-payload-size:
11261     # . prologue
11262     55/push-ebp
11263     89/<- %ebp 4/r32/esp
11264     # setup
11265     (clear-stream _test-input-stream)
11266     (clear-stream $_test-input-buffered-file->buffer)
11267     (clear-stream _test-output-stream)
11268     (clear-stream $_test-output-buffered-file->buffer)
11269     #
11270     (write _test-input-stream "fn foo {\n")
11271     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11272     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11273     (write _test-input-stream "  write-to-stream s, o\n")
11274     (write _test-input-stream "}\n")
11275     # convert
11276     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11277     # registers except esp clobbered at this point
11278     # restore ed
11279     89/<- %edx 4/r32/esp
11280     (flush _test-output-buffered-file)
11281     (flush _test-error-buffered-file)
11282 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11288     # check output
11289     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
11290     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
11291     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
11292     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
11293     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
11294     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
11295     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
11296     (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")
11297     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
11298     (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")
11299     (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")
11300     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
11301     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
11302     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
11303     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
11304     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
11305     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
11306     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
11307     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
11308     # . epilogue
11309     89/<- %esp 5/r32/ebp
11310     5d/pop-to-ebp
11311     c3/return
11312 
11313 test-write-to-stream-with-non-stream-atom-base-type:
11314     # . prologue
11315     55/push-ebp
11316     89/<- %ebp 4/r32/esp
11317     # setup
11318     (clear-stream _test-input-stream)
11319     (clear-stream $_test-input-buffered-file->buffer)
11320     (clear-stream _test-output-stream)
11321     (clear-stream $_test-output-buffered-file->buffer)
11322     (clear-stream _test-error-stream)
11323     (clear-stream $_test-error-buffered-file->buffer)
11324     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11325     68/push 0/imm32
11326     68/push 0/imm32
11327     89/<- %edx 4/r32/esp
11328     (tailor-exit-descriptor %edx 0x10)
11329     #
11330     (write _test-input-stream "fn foo {\n")
11331     (write _test-input-stream "  var a: int\n")
11332     (write _test-input-stream "  write-to-stream a, 0\n")
11333     (write _test-input-stream "}\n")
11334     # convert
11335     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11336     # registers except esp clobbered at this point
11337     # restore ed
11338     89/<- %edx 4/r32/esp
11339     (flush _test-output-buffered-file)
11340     (flush _test-error-buffered-file)
11341 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11347     # check output
11348     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
11349     (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")
11350     # check that stop(1) was called
11351     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
11352     # don't restore from ebp
11353     81 0/subop/add %esp 8/imm32
11354     # . epilogue
11355     5d/pop-to-ebp
11356     c3/return
11357 
11358 test-write-to-stream-with-non-stream-compound-base-type:
11359     # . prologue
11360     55/push-ebp
11361     89/<- %ebp 4/r32/esp
11362     # setup
11363     (clear-stream _test-input-stream)
11364     (clear-stream $_test-input-buffered-file->buffer)
11365     (clear-stream _test-output-stream)
11366     (clear-stream $_test-output-buffered-file->buffer)
11367     (clear-stream _test-error-stream)
11368     (clear-stream $_test-error-buffered-file->buffer)
11369     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11370     68/push 0/imm32
11371     68/push 0/imm32
11372     89/<- %edx 4/r32/esp
11373     (tailor-exit-descriptor %edx 0x10)
11374     #
11375     (write _test-input-stream "fn foo {\n")
11376     (write _test-input-stream "  var a: (handle int)\n")
11377     (write _test-input-stream "  write-to-stream a, 0\n")
11378     (write _test-input-stream "}\n")
11379     # convert
11380     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11381     # registers except esp clobbered at this point
11382     # restore ed
11383     89/<- %edx 4/r32/esp
11384     (flush _test-output-buffered-file)
11385     (flush _test-error-buffered-file)
11386 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11392     # check output
11393     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
11394     (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")
11395     # check that stop(1) was called
11396     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
11397     # don't restore from ebp
11398     81 0/subop/add %esp 8/imm32
11399     # . epilogue
11400     5d/pop-to-ebp
11401     c3/return
11402 
11403 test-write-to-stream-with-non-stream-compound-base-type-2:
11404     # . prologue
11405     55/push-ebp
11406     89/<- %ebp 4/r32/esp
11407     # setup
11408     (clear-stream _test-input-stream)
11409     (clear-stream $_test-input-buffered-file->buffer)
11410     (clear-stream _test-output-stream)
11411     (clear-stream $_test-output-buffered-file->buffer)
11412     (clear-stream _test-error-stream)
11413     (clear-stream $_test-error-buffered-file->buffer)
11414     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11415     68/push 0/imm32
11416     68/push 0/imm32
11417     89/<- %edx 4/r32/esp
11418     (tailor-exit-descriptor %edx 0x10)
11419     #
11420     (write _test-input-stream "fn foo {\n")
11421     (write _test-input-stream "  var a: (addr int)\n")
11422     (write _test-input-stream "  write-to-stream a, 0\n")
11423     (write _test-input-stream "}\n")
11424     # convert
11425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11426     # registers except esp clobbered at this point
11427     # restore ed
11428     89/<- %edx 4/r32/esp
11429     (flush _test-output-buffered-file)
11430     (flush _test-error-buffered-file)
11431 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11437     # check output
11438     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
11439     (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")
11440     # check that stop(1) was called
11441     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
11442     # don't restore from ebp
11443     81 0/subop/add %esp 8/imm32
11444     # . epilogue
11445     5d/pop-to-ebp
11446     c3/return
11447 
11448 test-write-to-stream-with-stream-atom-base-type:
11449     # . prologue
11450     55/push-ebp
11451     89/<- %ebp 4/r32/esp
11452     # setup
11453     (clear-stream _test-input-stream)
11454     (clear-stream $_test-input-buffered-file->buffer)
11455     (clear-stream _test-output-stream)
11456     (clear-stream $_test-output-buffered-file->buffer)
11457     (clear-stream _test-error-stream)
11458     (clear-stream $_test-error-buffered-file->buffer)
11459     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11460     68/push 0/imm32
11461     68/push 0/imm32
11462     89/<- %edx 4/r32/esp
11463     (tailor-exit-descriptor %edx 0x10)
11464     #
11465     (write _test-input-stream "fn foo {\n")
11466     (write _test-input-stream "  var a: stream\n")
11467     (write _test-input-stream "  write-to-stream a, 0\n")
11468     (write _test-input-stream "}\n")
11469     # convert
11470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11471     # registers except esp clobbered at this point
11472     # restore ed
11473     89/<- %edx 4/r32/esp
11474     (flush _test-output-buffered-file)
11475     (flush _test-error-buffered-file)
11476 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11482     # check output
11483     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
11484     (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")
11485     # check that stop(1) was called
11486     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
11487     # don't restore from ebp
11488     81 0/subop/add %esp 8/imm32
11489     # . epilogue
11490     5d/pop-to-ebp
11491     c3/return
11492 
11493 test-write-to-stream-with-wrong-index-type:
11494     # . prologue
11495     55/push-ebp
11496     89/<- %ebp 4/r32/esp
11497     # setup
11498     (clear-stream _test-input-stream)
11499     (clear-stream $_test-input-buffered-file->buffer)
11500     (clear-stream _test-output-stream)
11501     (clear-stream $_test-output-buffered-file->buffer)
11502     (clear-stream _test-error-stream)
11503     (clear-stream $_test-error-buffered-file->buffer)
11504     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11505     68/push 0/imm32
11506     68/push 0/imm32
11507     89/<- %edx 4/r32/esp
11508     (tailor-exit-descriptor %edx 0x10)
11509     #
11510     (write _test-input-stream "fn foo {\n")
11511     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
11512     (write _test-input-stream "  var b: boolean\n")
11513     (write _test-input-stream "  write-to-stream a, b\n")
11514     (write _test-input-stream "}\n")
11515     # convert
11516     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11517     # registers except esp clobbered at this point
11518     # restore ed
11519     89/<- %edx 4/r32/esp
11520     (flush _test-output-buffered-file)
11521     (flush _test-error-buffered-file)
11522 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11528     # check output
11529     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
11530     (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")
11531     # check that stop(1) was called
11532     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
11533     # don't restore from ebp
11534     81 0/subop/add %esp 8/imm32
11535     # . epilogue
11536     5d/pop-to-ebp
11537     c3/return
11538 
11539 test-write-to-stream-with-no-inouts:
11540     # . prologue
11541     55/push-ebp
11542     89/<- %ebp 4/r32/esp
11543     # setup
11544     (clear-stream _test-input-stream)
11545     (clear-stream $_test-input-buffered-file->buffer)
11546     (clear-stream _test-output-stream)
11547     (clear-stream $_test-output-buffered-file->buffer)
11548     (clear-stream _test-error-stream)
11549     (clear-stream $_test-error-buffered-file->buffer)
11550     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11551     68/push 0/imm32
11552     68/push 0/imm32
11553     89/<- %edx 4/r32/esp
11554     (tailor-exit-descriptor %edx 0x10)
11555     #
11556     (write _test-input-stream "fn foo {\n")
11557     (write _test-input-stream "  write-to-stream\n")
11558     (write _test-input-stream "}\n")
11559     # convert
11560     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11561     # registers except esp clobbered at this point
11562     # restore ed
11563     89/<- %edx 4/r32/esp
11564     (flush _test-output-buffered-file)
11565     (flush _test-error-buffered-file)
11566 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11572     # check output
11573     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
11574     (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")
11575     # check that stop(1) was called
11576     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
11577     # don't restore from ebp
11578     81 0/subop/add %esp 8/imm32
11579     # . epilogue
11580     5d/pop-to-ebp
11581     c3/return
11582 
11583 test-write-to-stream-with-too-few-inouts:
11584     # . prologue
11585     55/push-ebp
11586     89/<- %ebp 4/r32/esp
11587     # setup
11588     (clear-stream _test-input-stream)
11589     (clear-stream $_test-input-buffered-file->buffer)
11590     (clear-stream _test-output-stream)
11591     (clear-stream $_test-output-buffered-file->buffer)
11592     (clear-stream _test-error-stream)
11593     (clear-stream $_test-error-buffered-file->buffer)
11594     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11595     68/push 0/imm32
11596     68/push 0/imm32
11597     89/<- %edx 4/r32/esp
11598     (tailor-exit-descriptor %edx 0x10)
11599     #
11600     (write _test-input-stream "fn foo {\n")
11601     (write _test-input-stream "  var a: (addr stream int)\n")
11602     (write _test-input-stream "  write-to-stream a\n")
11603     (write _test-input-stream "}\n")
11604     # convert
11605     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11606     # registers except esp clobbered at this point
11607     # restore ed
11608     89/<- %edx 4/r32/esp
11609     (flush _test-output-buffered-file)
11610     (flush _test-error-buffered-file)
11611 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11617     # check output
11618     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
11619     (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")
11620     # check that stop(1) was called
11621     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
11622     # don't restore from ebp
11623     81 0/subop/add %esp 8/imm32
11624     # . epilogue
11625     5d/pop-to-ebp
11626     c3/return
11627 
11628 test-write-to-stream-with-too-many-inouts:
11629     # . prologue
11630     55/push-ebp
11631     89/<- %ebp 4/r32/esp
11632     # setup
11633     (clear-stream _test-input-stream)
11634     (clear-stream $_test-input-buffered-file->buffer)
11635     (clear-stream _test-output-stream)
11636     (clear-stream $_test-output-buffered-file->buffer)
11637     (clear-stream _test-error-stream)
11638     (clear-stream $_test-error-buffered-file->buffer)
11639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11640     68/push 0/imm32
11641     68/push 0/imm32
11642     89/<- %edx 4/r32/esp
11643     (tailor-exit-descriptor %edx 0x10)
11644     #
11645     (write _test-input-stream "fn foo {\n")
11646     (write _test-input-stream "  var a: (addr stream int)\n")
11647     (write _test-input-stream "  var b: (addr int)\n")
11648     (write _test-input-stream "  write-to-stream a, b, 0\n")
11649     (write _test-input-stream "}\n")
11650     # convert
11651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11652     # registers except esp clobbered at this point
11653     # restore ed
11654     89/<- %edx 4/r32/esp
11655     (flush _test-output-buffered-file)
11656     (flush _test-error-buffered-file)
11657 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11663     # check output
11664     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
11665     (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")
11666     # check that stop(1) was called
11667     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
11668     # don't restore from ebp
11669     81 0/subop/add %esp 8/imm32
11670     # . epilogue
11671     5d/pop-to-ebp
11672     c3/return
11673 
11674 test-write-to-stream-with-output:
11675     # . prologue
11676     55/push-ebp
11677     89/<- %ebp 4/r32/esp
11678     # setup
11679     (clear-stream _test-input-stream)
11680     (clear-stream $_test-input-buffered-file->buffer)
11681     (clear-stream _test-output-stream)
11682     (clear-stream $_test-output-buffered-file->buffer)
11683     (clear-stream _test-error-stream)
11684     (clear-stream $_test-error-buffered-file->buffer)
11685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11686     68/push 0/imm32
11687     68/push 0/imm32
11688     89/<- %edx 4/r32/esp
11689     (tailor-exit-descriptor %edx 0x10)
11690     #
11691     (write _test-input-stream "fn foo {\n")
11692     (write _test-input-stream "  var a: (addr stream int)\n")
11693     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11694     (write _test-input-stream "  b <- write-to-stream a, b\n")
11695     (write _test-input-stream "}\n")
11696     # convert
11697     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11698     # registers except esp clobbered at this point
11699     # restore ed
11700     89/<- %edx 4/r32/esp
11701     (flush _test-output-buffered-file)
11702     (flush _test-error-buffered-file)
11703 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11709     # check output
11710     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
11711     (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")
11712     # check that stop(1) was called
11713     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
11714     # don't restore from ebp
11715     81 0/subop/add %esp 8/imm32
11716     # . epilogue
11717     5d/pop-to-ebp
11718     c3/return
11719 
11720 test-length-with-non-array-atom-base-type:
11721     # . prologue
11722     55/push-ebp
11723     89/<- %ebp 4/r32/esp
11724     # setup
11725     (clear-stream _test-input-stream)
11726     (clear-stream $_test-input-buffered-file->buffer)
11727     (clear-stream _test-output-stream)
11728     (clear-stream $_test-output-buffered-file->buffer)
11729     (clear-stream _test-error-stream)
11730     (clear-stream $_test-error-buffered-file->buffer)
11731     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11732     68/push 0/imm32
11733     68/push 0/imm32
11734     89/<- %edx 4/r32/esp
11735     (tailor-exit-descriptor %edx 0x10)
11736     #
11737     (write _test-input-stream "fn foo {\n")
11738     (write _test-input-stream "  var a: int\n")
11739     (write _test-input-stream "  var c/ecx: int <- length a\n")
11740     (write _test-input-stream "}\n")
11741     # convert
11742     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11743     # registers except esp clobbered at this point
11744     # restore ed
11745     89/<- %edx 4/r32/esp
11746     (flush _test-output-buffered-file)
11747     (flush _test-error-buffered-file)
11748 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11754     # check output
11755     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
11756     (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")
11757     # check that stop(1) was called
11758     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
11759     # don't restore from ebp
11760     81 0/subop/add %esp 8/imm32
11761     # . epilogue
11762     5d/pop-to-ebp
11763     c3/return
11764 
11765 test-length-with-non-array-compound-base-type:
11766     # . prologue
11767     55/push-ebp
11768     89/<- %ebp 4/r32/esp
11769     # setup
11770     (clear-stream _test-input-stream)
11771     (clear-stream $_test-input-buffered-file->buffer)
11772     (clear-stream _test-output-stream)
11773     (clear-stream $_test-output-buffered-file->buffer)
11774     (clear-stream _test-error-stream)
11775     (clear-stream $_test-error-buffered-file->buffer)
11776     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11777     68/push 0/imm32
11778     68/push 0/imm32
11779     89/<- %edx 4/r32/esp
11780     (tailor-exit-descriptor %edx 0x10)
11781     #
11782     (write _test-input-stream "fn foo {\n")
11783     (write _test-input-stream "  var a: (handle int)\n")
11784     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
11785     (write _test-input-stream "}\n")
11786     # convert
11787     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11788     # registers except esp clobbered at this point
11789     # restore ed
11790     89/<- %edx 4/r32/esp
11791     (flush _test-output-buffered-file)
11792     (flush _test-error-buffered-file)
11793 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11799     # check output
11800     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
11801     (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")
11802     # check that stop(1) was called
11803     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
11804     # don't restore from ebp
11805     81 0/subop/add %esp 8/imm32
11806     # . epilogue
11807     5d/pop-to-ebp
11808     c3/return
11809 
11810 test-length-with-non-array-compound-base-type-2:
11811     # . prologue
11812     55/push-ebp
11813     89/<- %ebp 4/r32/esp
11814     # setup
11815     (clear-stream _test-input-stream)
11816     (clear-stream $_test-input-buffered-file->buffer)
11817     (clear-stream _test-output-stream)
11818     (clear-stream $_test-output-buffered-file->buffer)
11819     (clear-stream _test-error-stream)
11820     (clear-stream $_test-error-buffered-file->buffer)
11821     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11822     68/push 0/imm32
11823     68/push 0/imm32
11824     89/<- %edx 4/r32/esp
11825     (tailor-exit-descriptor %edx 0x10)
11826     #
11827     (write _test-input-stream "fn foo {\n")
11828     (write _test-input-stream "  var a: (addr int)\n")
11829     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
11830     (write _test-input-stream "}\n")
11831     # convert
11832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11833     # registers except esp clobbered at this point
11834     # restore ed
11835     89/<- %edx 4/r32/esp
11836     (flush _test-output-buffered-file)
11837     (flush _test-error-buffered-file)
11838 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11844     # check output
11845     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
11846     (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")
11847     # check that stop(1) was called
11848     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
11849     # don't restore from ebp
11850     81 0/subop/add %esp 8/imm32
11851     # . epilogue
11852     5d/pop-to-ebp
11853     c3/return
11854 
11855 test-length-with-array-atom-base-type:
11856     # . prologue
11857     55/push-ebp
11858     89/<- %ebp 4/r32/esp
11859     # setup
11860     (clear-stream _test-input-stream)
11861     (clear-stream $_test-input-buffered-file->buffer)
11862     (clear-stream _test-output-stream)
11863     (clear-stream $_test-output-buffered-file->buffer)
11864     (clear-stream _test-error-stream)
11865     (clear-stream $_test-error-buffered-file->buffer)
11866     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11867     68/push 0/imm32
11868     68/push 0/imm32
11869     89/<- %edx 4/r32/esp
11870     (tailor-exit-descriptor %edx 0x10)
11871     #
11872     (write _test-input-stream "fn foo {\n")
11873     (write _test-input-stream "  var a: array\n")
11874     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
11875     (write _test-input-stream "}\n")
11876     # convert
11877     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11878     # registers except esp clobbered at this point
11879     # restore ed
11880     89/<- %edx 4/r32/esp
11881     (flush _test-output-buffered-file)
11882     (flush _test-error-buffered-file)
11883 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11889     # check output
11890     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
11891     (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")
11892     # check that stop(1) was called
11893     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
11894     # don't restore from ebp
11895     81 0/subop/add %esp 8/imm32
11896     # . epilogue
11897     5d/pop-to-ebp
11898     c3/return
11899 
11900 test-length-with-addr-base-on-stack:
11901     # . prologue
11902     55/push-ebp
11903     89/<- %ebp 4/r32/esp
11904     # setup
11905     (clear-stream _test-input-stream)
11906     (clear-stream $_test-input-buffered-file->buffer)
11907     (clear-stream _test-output-stream)
11908     (clear-stream $_test-output-buffered-file->buffer)
11909     (clear-stream _test-error-stream)
11910     (clear-stream $_test-error-buffered-file->buffer)
11911     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11912     68/push 0/imm32
11913     68/push 0/imm32
11914     89/<- %edx 4/r32/esp
11915     (tailor-exit-descriptor %edx 0x10)
11916     #
11917     (write _test-input-stream "fn foo {\n")
11918     (write _test-input-stream "  var a: (addr array int)\n")
11919     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
11920     (write _test-input-stream "}\n")
11921     # convert
11922     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11923     # registers except esp clobbered at this point
11924     # restore ed
11925     89/<- %edx 4/r32/esp
11926     (flush _test-output-buffered-file)
11927     (flush _test-error-buffered-file)
11928 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11934     # check output
11935     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
11936     (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")
11937     # check that stop(1) was called
11938     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
11939     # don't restore from ebp
11940     81 0/subop/add %esp 8/imm32
11941     # . epilogue
11942     5d/pop-to-ebp
11943     c3/return
11944 
11945 test-length-with-wrong-output-type:
11946     # . prologue
11947     55/push-ebp
11948     89/<- %ebp 4/r32/esp
11949     # setup
11950     (clear-stream _test-input-stream)
11951     (clear-stream $_test-input-buffered-file->buffer)
11952     (clear-stream _test-output-stream)
11953     (clear-stream $_test-output-buffered-file->buffer)
11954     (clear-stream _test-error-stream)
11955     (clear-stream $_test-error-buffered-file->buffer)
11956     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11957     68/push 0/imm32
11958     68/push 0/imm32
11959     89/<- %edx 4/r32/esp
11960     (tailor-exit-descriptor %edx 0x10)
11961     #
11962     (write _test-input-stream "fn foo {\n")
11963     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11964     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
11965     (write _test-input-stream "}\n")
11966     # convert
11967     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11968     # registers except esp clobbered at this point
11969     # restore ed
11970     89/<- %edx 4/r32/esp
11971     (flush _test-output-buffered-file)
11972     (flush _test-error-buffered-file)
11973 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11979     # check output
11980     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
11981     (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")
11982     # check that stop(1) was called
11983     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
11984     # don't restore from ebp
11985     81 0/subop/add %esp 8/imm32
11986     # . epilogue
11987     5d/pop-to-ebp
11988     c3/return
11989 
11990 test-length-with-wrong-output-compound-type:
11991     # . prologue
11992     55/push-ebp
11993     89/<- %ebp 4/r32/esp
11994     # setup
11995     (clear-stream _test-input-stream)
11996     (clear-stream $_test-input-buffered-file->buffer)
11997     (clear-stream _test-output-stream)
11998     (clear-stream $_test-output-buffered-file->buffer)
11999     (clear-stream _test-error-stream)
12000     (clear-stream $_test-error-buffered-file->buffer)
12001     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12002     68/push 0/imm32
12003     68/push 0/imm32
12004     89/<- %edx 4/r32/esp
12005     (tailor-exit-descriptor %edx 0x10)
12006     #
12007     (write _test-input-stream "fn foo {\n")
12008     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12009     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
12010     (write _test-input-stream "}\n")
12011     # convert
12012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12013     # registers except esp clobbered at this point
12014     # restore ed
12015     89/<- %edx 4/r32/esp
12016     (flush _test-output-buffered-file)
12017     (flush _test-error-buffered-file)
12018 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12024     # check output
12025     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
12026     (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")
12027     # check that stop(1) was called
12028     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
12029     # don't restore from ebp
12030     81 0/subop/add %esp 8/imm32
12031     # . epilogue
12032     5d/pop-to-ebp
12033     c3/return
12034 
12035 test-length-with-no-inouts:
12036     # . prologue
12037     55/push-ebp
12038     89/<- %ebp 4/r32/esp
12039     # setup
12040     (clear-stream _test-input-stream)
12041     (clear-stream $_test-input-buffered-file->buffer)
12042     (clear-stream _test-output-stream)
12043     (clear-stream $_test-output-buffered-file->buffer)
12044     (clear-stream _test-error-stream)
12045     (clear-stream $_test-error-buffered-file->buffer)
12046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12047     68/push 0/imm32
12048     68/push 0/imm32
12049     89/<- %edx 4/r32/esp
12050     (tailor-exit-descriptor %edx 0x10)
12051     #
12052     (write _test-input-stream "fn foo {\n")
12053     (write _test-input-stream "  var c/ecx: int <- length\n")
12054     (write _test-input-stream "}\n")
12055     # convert
12056     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12057     # registers except esp clobbered at this point
12058     # restore ed
12059     89/<- %edx 4/r32/esp
12060     (flush _test-output-buffered-file)
12061     (flush _test-error-buffered-file)
12062 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12068     # check output
12069     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
12070     (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")
12071     # check that stop(1) was called
12072     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
12073     # don't restore from ebp
12074     81 0/subop/add %esp 8/imm32
12075     # . epilogue
12076     5d/pop-to-ebp
12077     c3/return
12078 
12079 test-length-with-too-many-inouts:
12080     # . prologue
12081     55/push-ebp
12082     89/<- %ebp 4/r32/esp
12083     # setup
12084     (clear-stream _test-input-stream)
12085     (clear-stream $_test-input-buffered-file->buffer)
12086     (clear-stream _test-output-stream)
12087     (clear-stream $_test-output-buffered-file->buffer)
12088     (clear-stream _test-error-stream)
12089     (clear-stream $_test-error-buffered-file->buffer)
12090     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12091     68/push 0/imm32
12092     68/push 0/imm32
12093     89/<- %edx 4/r32/esp
12094     (tailor-exit-descriptor %edx 0x10)
12095     #
12096     (write _test-input-stream "fn foo {\n")
12097     (write _test-input-stream "  var a: (array int 3)\n")
12098     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
12099     (write _test-input-stream "}\n")
12100     # convert
12101     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12102     # registers except esp clobbered at this point
12103     # restore ed
12104     89/<- %edx 4/r32/esp
12105     (flush _test-output-buffered-file)
12106     (flush _test-error-buffered-file)
12107 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12113     # check output
12114     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
12115     (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")
12116     # check that stop(1) was called
12117     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
12118     # don't restore from ebp
12119     81 0/subop/add %esp 8/imm32
12120     # . epilogue
12121     5d/pop-to-ebp
12122     c3/return
12123 
12124 test-length-with-no-output:
12125     # . prologue
12126     55/push-ebp
12127     89/<- %ebp 4/r32/esp
12128     # setup
12129     (clear-stream _test-input-stream)
12130     (clear-stream $_test-input-buffered-file->buffer)
12131     (clear-stream _test-output-stream)
12132     (clear-stream $_test-output-buffered-file->buffer)
12133     (clear-stream _test-error-stream)
12134     (clear-stream $_test-error-buffered-file->buffer)
12135     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12136     68/push 0/imm32
12137     68/push 0/imm32
12138     89/<- %edx 4/r32/esp
12139     (tailor-exit-descriptor %edx 0x10)
12140     #
12141     (write _test-input-stream "fn foo {\n")
12142     (write _test-input-stream "  var a: (array int 3)\n")
12143     (write _test-input-stream "  length a\n")
12144     (write _test-input-stream "}\n")
12145     # convert
12146     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12147     # registers except esp clobbered at this point
12148     # restore ed
12149     89/<- %edx 4/r32/esp
12150     (flush _test-output-buffered-file)
12151     (flush _test-error-buffered-file)
12152 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12158     # check output
12159     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
12160     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
12161     # check that stop(1) was called
12162     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
12163     # don't restore from ebp
12164     81 0/subop/add %esp 8/imm32
12165     # . epilogue
12166     5d/pop-to-ebp
12167     c3/return
12168 
12169 test-length-with-too-many-outputs:
12170     # . prologue
12171     55/push-ebp
12172     89/<- %ebp 4/r32/esp
12173     # setup
12174     (clear-stream _test-input-stream)
12175     (clear-stream $_test-input-buffered-file->buffer)
12176     (clear-stream _test-output-stream)
12177     (clear-stream $_test-output-buffered-file->buffer)
12178     (clear-stream _test-error-stream)
12179     (clear-stream $_test-error-buffered-file->buffer)
12180     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12181     68/push 0/imm32
12182     68/push 0/imm32
12183     89/<- %edx 4/r32/esp
12184     (tailor-exit-descriptor %edx 0x10)
12185     #
12186     (write _test-input-stream "fn foo {\n")
12187     (write _test-input-stream "  var a: (array int 3)\n")
12188     (write _test-input-stream "  var b/eax: int <- copy 0\n")
12189     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
12190     (write _test-input-stream "  b, c <- length a\n")
12191     (write _test-input-stream "}\n")
12192     # convert
12193     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12194     # registers except esp clobbered at this point
12195     # restore ed
12196     89/<- %edx 4/r32/esp
12197     (flush _test-output-buffered-file)
12198     (flush _test-error-buffered-file)
12199 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12205     # check output
12206     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
12207     (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")
12208     # check that stop(1) was called
12209     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
12210     # don't restore from ebp
12211     81 0/subop/add %esp 8/imm32
12212     # . epilogue
12213     5d/pop-to-ebp
12214     c3/return
12215 
12216 test-convert-function-with-return-register-and-local:
12217     # . prologue
12218     55/push-ebp
12219     89/<- %ebp 4/r32/esp
12220     # setup
12221     (clear-stream _test-input-stream)
12222     (clear-stream $_test-input-buffered-file->buffer)
12223     (clear-stream _test-output-stream)
12224     (clear-stream $_test-output-buffered-file->buffer)
12225     #
12226     (write _test-input-stream "fn foo -> _/eax: int {\n")
12227     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12228     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12229     (write _test-input-stream "  return y\n")
12230     (write _test-input-stream "}\n")
12231     # convert
12232     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12233     (flush _test-output-buffered-file)
12234 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12240     # check output
12241     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
12242     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
12243     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
12244     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
12245     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
12246     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
12247     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
12248     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
12249     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
12250     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
12251     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
12252     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
12253     (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")
12254     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
12255     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
12256     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
12257     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
12258     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
12259     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
12260     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
12261     # . epilogue
12262     89/<- %esp 5/r32/ebp
12263     5d/pop-to-ebp
12264     c3/return
12265 
12266 test-convert-function-with-return-register-and-local-2:
12267     # . prologue
12268     55/push-ebp
12269     89/<- %ebp 4/r32/esp
12270     # setup
12271     (clear-stream _test-input-stream)
12272     (clear-stream $_test-input-buffered-file->buffer)
12273     (clear-stream _test-output-stream)
12274     (clear-stream $_test-output-buffered-file->buffer)
12275     #
12276     (write _test-input-stream "fn foo -> _/eax: int {\n")
12277     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12278     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12279     (write _test-input-stream "  return z\n")
12280     (write _test-input-stream "}\n")
12281     # convert
12282     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12283     (flush _test-output-buffered-file)
12284 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12290     # check output
12291     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
12292     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
12293     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
12294     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
12295     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
12296     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
12297     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
12298     (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")
12299     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
12300     (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")
12301     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
12302     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
12303     (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")
12304     (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")
12305     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
12306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
12307     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
12308     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
12309     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
12310     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
12311     # . epilogue
12312     89/<- %esp 5/r32/ebp
12313     5d/pop-to-ebp
12314     c3/return
12315 
12316 test-convert-function-with-return-float-register-and-local:
12317     # . prologue
12318     55/push-ebp
12319     89/<- %ebp 4/r32/esp
12320     # setup
12321     (clear-stream _test-input-stream)
12322     (clear-stream $_test-input-buffered-file->buffer)
12323     (clear-stream _test-output-stream)
12324     (clear-stream $_test-output-buffered-file->buffer)
12325     #
12326     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
12327     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12328     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
12329     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
12330     (write _test-input-stream "  return g\n")
12331     (write _test-input-stream "}\n")
12332     # convert
12333     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12334     (flush _test-output-buffered-file)
12335 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12341     # check output
12342     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
12343     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
12344     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
12345     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
12346     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
12347     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
12348     (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
12349     (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")
12350     (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
12351     (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")
12352     (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")
12353     (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
12354     (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")
12355     (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")
12356     (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
12357     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
12358     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
12359     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
12360     (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
12361     (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")
12362     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
12363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
12364     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
12365     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
12366     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
12367     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
12368     # . epilogue
12369     89/<- %esp 5/r32/ebp
12370     5d/pop-to-ebp
12371     c3/return
12372 
12373 test-convert-function-with-return-and-local-vars:
12374     # . prologue
12375     55/push-ebp
12376     89/<- %ebp 4/r32/esp
12377     # setup
12378     (clear-stream _test-input-stream)
12379     (clear-stream $_test-input-buffered-file->buffer)
12380     (clear-stream _test-output-stream)
12381     (clear-stream $_test-output-buffered-file->buffer)
12382     #
12383     (write _test-input-stream "fn foo -> _/eax: int {\n")
12384     (write _test-input-stream "  {\n")
12385     (write _test-input-stream "    var x: int\n")
12386     (write _test-input-stream "    {\n")
12387     (write _test-input-stream "      var y: int\n")
12388     (write _test-input-stream "      return y\n")
12389     (write _test-input-stream "      increment x\n")
12390     (write _test-input-stream "    }\n")
12391     (write _test-input-stream "  }\n")
12392     (write _test-input-stream "  return 0\n")
12393     (write _test-input-stream "}\n")
12394     # convert
12395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12396     (flush _test-output-buffered-file)
12397 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12403     # check output
12404     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
12405     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
12406     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
12407     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
12408     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
12409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
12410     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
12411     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
12412     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
12413     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
12414     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
12415     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
12416     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
12417     (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")
12418     (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")
12419     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
12420     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
12421     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
12422     (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")
12423     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
12424     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
12425     (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")
12426     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
12427     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
12428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
12429     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
12430     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
12431     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
12432     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
12433     # . epilogue
12434     89/<- %esp 5/r32/ebp
12435     5d/pop-to-ebp
12436     c3/return
12437 
12438 test-copy-object-with-no-inout:
12439     # . prologue
12440     55/push-ebp
12441     89/<- %ebp 4/r32/esp
12442     # setup
12443     (clear-stream _test-input-stream)
12444     (clear-stream $_test-input-buffered-file->buffer)
12445     (clear-stream _test-output-stream)
12446     (clear-stream $_test-output-buffered-file->buffer)
12447     (clear-stream _test-error-stream)
12448     (clear-stream $_test-error-buffered-file->buffer)
12449     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12450     68/push 0/imm32
12451     68/push 0/imm32
12452     89/<- %edx 4/r32/esp
12453     (tailor-exit-descriptor %edx 0x10)
12454     #
12455     (write _test-input-stream "fn foo {\n")
12456     (write _test-input-stream "  copy-object\n")
12457     (write _test-input-stream "}\n")
12458     # convert
12459     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12460     # registers except esp clobbered at this point
12461     # restore ed
12462     89/<- %edx 4/r32/esp
12463     (flush _test-output-buffered-file)
12464     (flush _test-error-buffered-file)
12465 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12471     # check output
12472     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
12473     (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")
12474     # check that stop(1) was called
12475     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
12476     # don't restore from ebp
12477     81 0/subop/add %esp 8/imm32
12478     # . epilogue
12479     5d/pop-to-ebp
12480     c3/return
12481 
12482 test-copy-object-with-no-input:
12483     # . prologue
12484     55/push-ebp
12485     89/<- %ebp 4/r32/esp
12486     # setup
12487     (clear-stream _test-input-stream)
12488     (clear-stream $_test-input-buffered-file->buffer)
12489     (clear-stream _test-output-stream)
12490     (clear-stream $_test-output-buffered-file->buffer)
12491     (clear-stream _test-error-stream)
12492     (clear-stream $_test-error-buffered-file->buffer)
12493     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12494     68/push 0/imm32
12495     68/push 0/imm32
12496     89/<- %edx 4/r32/esp
12497     (tailor-exit-descriptor %edx 0x10)
12498     #
12499     (write _test-input-stream "fn foo {\n")
12500     (write _test-input-stream "  var x: (addr int)\n")
12501     (write _test-input-stream "  copy-object x\n")
12502     (write _test-input-stream "}\n")
12503     # convert
12504     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12505     # registers except esp clobbered at this point
12506     # restore ed
12507     89/<- %edx 4/r32/esp
12508     (flush _test-output-buffered-file)
12509     (flush _test-error-buffered-file)
12510 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12516     # check output
12517     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-input: output should be empty")
12518     (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")
12519     # check that stop(1) was called
12520     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-input: exit status")
12521     # don't restore from ebp
12522     81 0/subop/add %esp 8/imm32
12523     # . epilogue
12524     5d/pop-to-ebp
12525     c3/return
12526 
12527 test-copy-object-with-too-many-inouts:
12528     # . prologue
12529     55/push-ebp
12530     89/<- %ebp 4/r32/esp
12531     # setup
12532     (clear-stream _test-input-stream)
12533     (clear-stream $_test-input-buffered-file->buffer)
12534     (clear-stream _test-output-stream)
12535     (clear-stream $_test-output-buffered-file->buffer)
12536     (clear-stream _test-error-stream)
12537     (clear-stream $_test-error-buffered-file->buffer)
12538     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12539     68/push 0/imm32
12540     68/push 0/imm32
12541     89/<- %edx 4/r32/esp
12542     (tailor-exit-descriptor %edx 0x10)
12543     #
12544     (write _test-input-stream "fn foo {\n")
12545     (write _test-input-stream "  var x: (addr boolean)\n")
12546     (write _test-input-stream "  copy-object x, x, x\n")
12547     (write _test-input-stream "}\n")
12548     # convert
12549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12550     # registers except esp clobbered at this point
12551     # restore ed
12552     89/<- %edx 4/r32/esp
12553     (flush _test-output-buffered-file)
12554     (flush _test-error-buffered-file)
12555 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12561     # check output
12562     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
12563     (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")
12564     # check that stop(1) was called
12565     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
12566     # don't restore from ebp
12567     81 0/subop/add %esp 8/imm32
12568     # . epilogue
12569     5d/pop-to-ebp
12570     c3/return
12571 
12572 test-copy-object-with-output:
12573     # . prologue
12574     55/push-ebp
12575     89/<- %ebp 4/r32/esp
12576     # setup
12577     (clear-stream _test-input-stream)
12578     (clear-stream $_test-input-buffered-file->buffer)
12579     (clear-stream _test-output-stream)
12580     (clear-stream $_test-output-buffered-file->buffer)
12581     (clear-stream _test-error-stream)
12582     (clear-stream $_test-error-buffered-file->buffer)
12583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12584     68/push 0/imm32
12585     68/push 0/imm32
12586     89/<- %edx 4/r32/esp
12587     (tailor-exit-descriptor %edx 0x10)
12588     #
12589     (write _test-input-stream "fn foo {\n")
12590     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
12591     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
12592     (write _test-input-stream "  x <- copy-object x, y\n")
12593     (write _test-input-stream "}\n")
12594     # convert
12595     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12596     # registers except esp clobbered at this point
12597     # restore ed
12598     89/<- %edx 4/r32/esp
12599     (flush _test-output-buffered-file)
12600     (flush _test-error-buffered-file)
12601 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12607     # check output
12608     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
12609     (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")
12610     # check that stop(1) was called
12611     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
12612     # don't restore from ebp
12613     81 0/subop/add %esp 8/imm32
12614     # . epilogue
12615     5d/pop-to-ebp
12616     c3/return
12617 
12618 test-copy-object-deref-address:
12619     # . prologue
12620     55/push-ebp
12621     89/<- %ebp 4/r32/esp
12622     # setup
12623     (clear-stream _test-input-stream)
12624     (clear-stream $_test-input-buffered-file->buffer)
12625     (clear-stream _test-output-stream)
12626     (clear-stream $_test-output-buffered-file->buffer)
12627     #
12628     (write _test-input-stream "fn foo {\n")
12629     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
12630     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
12631     (write _test-input-stream "  copy-object *y, x\n")
12632     (write _test-input-stream "}\n")
12633     # convert
12634     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12635     (flush _test-output-buffered-file)
12636 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12642     # not bothering checking output
12643     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-object-deref-address: error message")
12644     # . epilogue
12645     5d/pop-to-ebp
12646     c3/return
12647 
12648 test-copy-object-non-addr:
12649     # . prologue
12650     55/push-ebp
12651     89/<- %ebp 4/r32/esp
12652     # setup
12653     (clear-stream _test-input-stream)
12654     (clear-stream $_test-input-buffered-file->buffer)
12655     (clear-stream _test-output-stream)
12656     (clear-stream $_test-output-buffered-file->buffer)
12657     (clear-stream _test-error-stream)
12658     (clear-stream $_test-error-buffered-file->buffer)
12659     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12660     68/push 0/imm32
12661     68/push 0/imm32
12662     89/<- %edx 4/r32/esp
12663     (tailor-exit-descriptor %edx 0x10)
12664     #
12665     (write _test-input-stream "fn foo {\n")
12666     (write _test-input-stream "  var x: int\n")
12667     (write _test-input-stream "  var y: int\n")
12668     (write _test-input-stream "  copy-object y, x\n")
12669     (write _test-input-stream "}\n")
12670     # convert
12671     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12672     # registers except esp clobbered at this point
12673     # restore ed
12674     89/<- %edx 4/r32/esp
12675     (flush _test-output-buffered-file)
12676     (flush _test-error-buffered-file)
12677 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12683     # check output
12684     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
12685     (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")
12686     # check that stop(1) was called
12687     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
12688     # don't restore from ebp
12689     81 0/subop/add %esp 8/imm32
12690     # . epilogue
12691     5d/pop-to-ebp
12692     c3/return
12693 
12694 test-copy-object-non-equal:
12695     # . prologue
12696     55/push-ebp
12697     89/<- %ebp 4/r32/esp
12698     # setup
12699     (clear-stream _test-input-stream)
12700     (clear-stream $_test-input-buffered-file->buffer)
12701     (clear-stream _test-output-stream)
12702     (clear-stream $_test-output-buffered-file->buffer)
12703     (clear-stream _test-error-stream)
12704     (clear-stream $_test-error-buffered-file->buffer)
12705     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12706     68/push 0/imm32
12707     68/push 0/imm32
12708     89/<- %edx 4/r32/esp
12709     (tailor-exit-descriptor %edx 0x10)
12710     #
12711     (write _test-input-stream "fn foo {\n")
12712     (write _test-input-stream "  var x: (addr int)\n")
12713     (write _test-input-stream "  var y: (addr boolean)\n")
12714     (write _test-input-stream "  copy-object y, x\n")
12715     (write _test-input-stream "}\n")
12716     # convert
12717     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12718     # registers except esp clobbered at this point
12719     # restore ed
12720     89/<- %edx 4/r32/esp
12721     (flush _test-output-buffered-file)
12722     (flush _test-error-buffered-file)
12723 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12729     # check output
12730     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
12731     (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")
12732     # check that stop(1) was called
12733     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
12734     # don't restore from ebp
12735     81 0/subop/add %esp 8/imm32
12736     # . epilogue
12737     5d/pop-to-ebp
12738     c3/return
12739 
12740 test-allocate-with-no-inout:
12741     # . prologue
12742     55/push-ebp
12743     89/<- %ebp 4/r32/esp
12744     # setup
12745     (clear-stream _test-input-stream)
12746     (clear-stream $_test-input-buffered-file->buffer)
12747     (clear-stream _test-output-stream)
12748     (clear-stream $_test-output-buffered-file->buffer)
12749     (clear-stream _test-error-stream)
12750     (clear-stream $_test-error-buffered-file->buffer)
12751     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12752     68/push 0/imm32
12753     68/push 0/imm32
12754     89/<- %edx 4/r32/esp
12755     (tailor-exit-descriptor %edx 0x10)
12756     #
12757     (write _test-input-stream "fn foo {\n")
12758     (write _test-input-stream "  allocate\n")
12759     (write _test-input-stream "}\n")
12760     # convert
12761     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12762     # registers except esp clobbered at this point
12763     # restore ed
12764     89/<- %edx 4/r32/esp
12765     (flush _test-output-buffered-file)
12766     (flush _test-error-buffered-file)
12767 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12773     # check output
12774     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
12775     (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")
12776     # check that stop(1) was called
12777     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
12778     # don't restore from ebp
12779     81 0/subop/add %esp 8/imm32
12780     # . epilogue
12781     5d/pop-to-ebp
12782     c3/return
12783 
12784 test-allocate-with-too-many-inouts:
12785     # . prologue
12786     55/push-ebp
12787     89/<- %ebp 4/r32/esp
12788     # setup
12789     (clear-stream _test-input-stream)
12790     (clear-stream $_test-input-buffered-file->buffer)
12791     (clear-stream _test-output-stream)
12792     (clear-stream $_test-output-buffered-file->buffer)
12793     (clear-stream _test-error-stream)
12794     (clear-stream $_test-error-buffered-file->buffer)
12795     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12796     68/push 0/imm32
12797     68/push 0/imm32
12798     89/<- %edx 4/r32/esp
12799     (tailor-exit-descriptor %edx 0x10)
12800     #
12801     (write _test-input-stream "fn foo {\n")
12802     (write _test-input-stream "  var x: (addr handle int)\n")
12803     (write _test-input-stream "  allocate x, 0\n")
12804     (write _test-input-stream "}\n")
12805     # convert
12806     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12807     # registers except esp clobbered at this point
12808     # restore ed
12809     89/<- %edx 4/r32/esp
12810     (flush _test-output-buffered-file)
12811     (flush _test-error-buffered-file)
12812 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12818     # check output
12819     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
12820     (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")
12821     # check that stop(1) was called
12822     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
12823     # don't restore from ebp
12824     81 0/subop/add %esp 8/imm32
12825     # . epilogue
12826     5d/pop-to-ebp
12827     c3/return
12828 
12829 test-allocate-with-output:
12830     # . prologue
12831     55/push-ebp
12832     89/<- %ebp 4/r32/esp
12833     # setup
12834     (clear-stream _test-input-stream)
12835     (clear-stream $_test-input-buffered-file->buffer)
12836     (clear-stream _test-output-stream)
12837     (clear-stream $_test-output-buffered-file->buffer)
12838     (clear-stream _test-error-stream)
12839     (clear-stream $_test-error-buffered-file->buffer)
12840     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12841     68/push 0/imm32
12842     68/push 0/imm32
12843     89/<- %edx 4/r32/esp
12844     (tailor-exit-descriptor %edx 0x10)
12845     #
12846     (write _test-input-stream "fn foo {\n")
12847     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
12848     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
12849     (write _test-input-stream "  x <- allocate y\n")
12850     (write _test-input-stream "}\n")
12851     # convert
12852     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12853     # registers except esp clobbered at this point
12854     # restore ed
12855     89/<- %edx 4/r32/esp
12856     (flush _test-output-buffered-file)
12857     (flush _test-error-buffered-file)
12858 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12864     # check output
12865     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
12866     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
12867     # check that stop(1) was called
12868     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
12869     # don't restore from ebp
12870     81 0/subop/add %esp 8/imm32
12871     # . epilogue
12872     5d/pop-to-ebp
12873     c3/return
12874 
12875 test-allocate-non-addr:
12876     # . prologue
12877     55/push-ebp
12878     89/<- %ebp 4/r32/esp
12879     # setup
12880     (clear-stream _test-input-stream)
12881     (clear-stream $_test-input-buffered-file->buffer)
12882     (clear-stream _test-output-stream)
12883     (clear-stream $_test-output-buffered-file->buffer)
12884     (clear-stream _test-error-stream)
12885     (clear-stream $_test-error-buffered-file->buffer)
12886     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12887     68/push 0/imm32
12888     68/push 0/imm32
12889     89/<- %edx 4/r32/esp
12890     (tailor-exit-descriptor %edx 0x10)
12891     #
12892     (write _test-input-stream "fn foo {\n")
12893     (write _test-input-stream "  var y: (handle int)\n")
12894     (write _test-input-stream "  allocate y\n")
12895     (write _test-input-stream "}\n")
12896     # convert
12897     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12898     # registers except esp clobbered at this point
12899     # restore ed
12900     89/<- %edx 4/r32/esp
12901     (flush _test-output-buffered-file)
12902     (flush _test-error-buffered-file)
12903 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12909     # check output
12910     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
12911     (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")
12912     # check that stop(1) was called
12913     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
12914     # don't restore from ebp
12915     81 0/subop/add %esp 8/imm32
12916     # . epilogue
12917     5d/pop-to-ebp
12918     c3/return
12919 
12920 test-allocate-non-addr-handle:
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 "  var y/ecx: (addr int) <- copy 0\n")
12939     (write _test-input-stream "  allocate y\n")
12940     (write _test-input-stream "}\n")
12941     # convert
12942     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12943     # registers except esp clobbered at this point
12944     # restore ed
12945     89/<- %edx 4/r32/esp
12946     (flush _test-output-buffered-file)
12947     (flush _test-error-buffered-file)
12948 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12954     # check output
12955     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
12956     (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")
12957     # check that stop(1) was called
12958     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
12959     # don't restore from ebp
12960     81 0/subop/add %esp 8/imm32
12961     # . epilogue
12962     5d/pop-to-ebp
12963     c3/return
12964 
12965 test-allocate-deref-address:
12966     # . prologue
12967     55/push-ebp
12968     89/<- %ebp 4/r32/esp
12969     # setup
12970     (clear-stream _test-input-stream)
12971     (clear-stream $_test-input-buffered-file->buffer)
12972     (clear-stream _test-output-stream)
12973     (clear-stream $_test-output-buffered-file->buffer)
12974     #
12975     (write _test-input-stream "fn foo {\n")
12976     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
12977     (write _test-input-stream "  allocate *y\n")
12978     (write _test-input-stream "}\n")
12979     # convert
12980     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12981     (flush _test-output-buffered-file)
12982 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12988     # not bothering checking output
12989     (check-next-stream-line-equal _test-error-stream  ""  "F - test-allocate-deref-address: error message")
12990     # . epilogue
12991     5d/pop-to-ebp
12992     c3/return
12993 
12994 test-populate-with-no-inout:
12995     # . prologue
12996     55/push-ebp
12997     89/<- %ebp 4/r32/esp
12998     # setup
12999     (clear-stream _test-input-stream)
13000     (clear-stream $_test-input-buffered-file->buffer)
13001     (clear-stream _test-output-stream)
13002     (clear-stream $_test-output-buffered-file->buffer)
13003     (clear-stream _test-error-stream)
13004     (clear-stream $_test-error-buffered-file->buffer)
13005     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13006     68/push 0/imm32
13007     68/push 0/imm32
13008     89/<- %edx 4/r32/esp
13009     (tailor-exit-descriptor %edx 0x10)
13010     #
13011     (write _test-input-stream "fn foo {\n")
13012     (write _test-input-stream "  populate\n")
13013     (write _test-input-stream "}\n")
13014     # convert
13015     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13016     # registers except esp clobbered at this point
13017     # restore ed
13018     89/<- %edx 4/r32/esp
13019     (flush _test-output-buffered-file)
13020     (flush _test-error-buffered-file)
13021 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13027     # check output
13028     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
13029     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
13030     # check that stop(1) was called
13031     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
13032     # don't restore from ebp
13033     81 0/subop/add %esp 8/imm32
13034     # . epilogue
13035     5d/pop-to-ebp
13036     c3/return
13037 
13038 test-populate-with-too-many-inouts:
13039     # . prologue
13040     55/push-ebp
13041     89/<- %ebp 4/r32/esp
13042     # setup
13043     (clear-stream _test-input-stream)
13044     (clear-stream $_test-input-buffered-file->buffer)
13045     (clear-stream _test-output-stream)
13046     (clear-stream $_test-output-buffered-file->buffer)
13047     (clear-stream _test-error-stream)
13048     (clear-stream $_test-error-buffered-file->buffer)
13049     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13050     68/push 0/imm32
13051     68/push 0/imm32
13052     89/<- %edx 4/r32/esp
13053     (tailor-exit-descriptor %edx 0x10)
13054     #
13055     (write _test-input-stream "fn foo {\n")
13056     (write _test-input-stream "  var x: (addr handle int)\n")
13057     (write _test-input-stream "  populate x, 3, 0\n")
13058     (write _test-input-stream "}\n")
13059     # convert
13060     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13061     # registers except esp clobbered at this point
13062     # restore ed
13063     89/<- %edx 4/r32/esp
13064     (flush _test-output-buffered-file)
13065     (flush _test-error-buffered-file)
13066 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13072     # check output
13073     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
13074     (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")
13075     # check that stop(1) was called
13076     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
13077     # don't restore from ebp
13078     81 0/subop/add %esp 8/imm32
13079     # . epilogue
13080     5d/pop-to-ebp
13081     c3/return
13082 
13083 test-populate-with-output:
13084     # . prologue
13085     55/push-ebp
13086     89/<- %ebp 4/r32/esp
13087     # setup
13088     (clear-stream _test-input-stream)
13089     (clear-stream $_test-input-buffered-file->buffer)
13090     (clear-stream _test-output-stream)
13091     (clear-stream $_test-output-buffered-file->buffer)
13092     (clear-stream _test-error-stream)
13093     (clear-stream $_test-error-buffered-file->buffer)
13094     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13095     68/push 0/imm32
13096     68/push 0/imm32
13097     89/<- %edx 4/r32/esp
13098     (tailor-exit-descriptor %edx 0x10)
13099     #
13100     (write _test-input-stream "fn foo {\n")
13101     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13102     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13103     (write _test-input-stream "  x <- populate y\n")
13104     (write _test-input-stream "}\n")
13105     # convert
13106     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13107     # registers except esp clobbered at this point
13108     # restore ed
13109     89/<- %edx 4/r32/esp
13110     (flush _test-output-buffered-file)
13111     (flush _test-error-buffered-file)
13112 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13118     # check output
13119     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
13120     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
13121     # check that stop(1) was called
13122     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
13123     # don't restore from ebp
13124     81 0/subop/add %esp 8/imm32
13125     # . epilogue
13126     5d/pop-to-ebp
13127     c3/return
13128 
13129 test-populate-non-addr:
13130     # . prologue
13131     55/push-ebp
13132     89/<- %ebp 4/r32/esp
13133     # setup
13134     (clear-stream _test-input-stream)
13135     (clear-stream $_test-input-buffered-file->buffer)
13136     (clear-stream _test-output-stream)
13137     (clear-stream $_test-output-buffered-file->buffer)
13138     (clear-stream _test-error-stream)
13139     (clear-stream $_test-error-buffered-file->buffer)
13140     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13141     68/push 0/imm32
13142     68/push 0/imm32
13143     89/<- %edx 4/r32/esp
13144     (tailor-exit-descriptor %edx 0x10)
13145     #
13146     (write _test-input-stream "fn foo {\n")
13147     (write _test-input-stream "  var y: (handle int)\n")
13148     (write _test-input-stream "  populate y, 3\n")
13149     (write _test-input-stream "}\n")
13150     # convert
13151     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13152     # registers except esp clobbered at this point
13153     # restore ed
13154     89/<- %edx 4/r32/esp
13155     (flush _test-output-buffered-file)
13156     (flush _test-error-buffered-file)
13157 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13163     # check output
13164     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
13165     (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")
13166     # check that stop(1) was called
13167     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
13168     # don't restore from ebp
13169     81 0/subop/add %esp 8/imm32
13170     # . epilogue
13171     5d/pop-to-ebp
13172     c3/return
13173 
13174 test-populate-non-addr-handle:
13175     # . prologue
13176     55/push-ebp
13177     89/<- %ebp 4/r32/esp
13178     # setup
13179     (clear-stream _test-input-stream)
13180     (clear-stream $_test-input-buffered-file->buffer)
13181     (clear-stream _test-output-stream)
13182     (clear-stream $_test-output-buffered-file->buffer)
13183     (clear-stream _test-error-stream)
13184     (clear-stream $_test-error-buffered-file->buffer)
13185     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13186     68/push 0/imm32
13187     68/push 0/imm32
13188     89/<- %edx 4/r32/esp
13189     (tailor-exit-descriptor %edx 0x10)
13190     #
13191     (write _test-input-stream "fn foo {\n")
13192     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13193     (write _test-input-stream "  populate y, 3\n")
13194     (write _test-input-stream "}\n")
13195     # convert
13196     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13197     # registers except esp clobbered at this point
13198     # restore ed
13199     89/<- %edx 4/r32/esp
13200     (flush _test-output-buffered-file)
13201     (flush _test-error-buffered-file)
13202 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13208     # check output
13209     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
13210     (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")
13211     # check that stop(1) was called
13212     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
13213     # don't restore from ebp
13214     81 0/subop/add %esp 8/imm32
13215     # . epilogue
13216     5d/pop-to-ebp
13217     c3/return
13218 
13219 test-populate-non-addr-handle-array:
13220     # . prologue
13221     55/push-ebp
13222     89/<- %ebp 4/r32/esp
13223     # setup
13224     (clear-stream _test-input-stream)
13225     (clear-stream $_test-input-buffered-file->buffer)
13226     (clear-stream _test-output-stream)
13227     (clear-stream $_test-output-buffered-file->buffer)
13228     (clear-stream _test-error-stream)
13229     (clear-stream $_test-error-buffered-file->buffer)
13230     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13231     68/push 0/imm32
13232     68/push 0/imm32
13233     89/<- %edx 4/r32/esp
13234     (tailor-exit-descriptor %edx 0x10)
13235     #
13236     (write _test-input-stream "fn foo {\n")
13237     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13238     (write _test-input-stream "  populate y, 3\n")
13239     (write _test-input-stream "}\n")
13240     # convert
13241     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13242     # registers except esp clobbered at this point
13243     # restore ed
13244     89/<- %edx 4/r32/esp
13245     (flush _test-output-buffered-file)
13246     (flush _test-error-buffered-file)
13247 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13253     # check output
13254     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
13255     (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")
13256     # check that stop(1) was called
13257     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
13258     # don't restore from ebp
13259     81 0/subop/add %esp 8/imm32
13260     # . epilogue
13261     5d/pop-to-ebp
13262     c3/return
13263 
13264 test-populate-deref-address:
13265     # . prologue
13266     55/push-ebp
13267     89/<- %ebp 4/r32/esp
13268     # setup
13269     (clear-stream _test-input-stream)
13270     (clear-stream $_test-input-buffered-file->buffer)
13271     (clear-stream _test-output-stream)
13272     (clear-stream $_test-output-buffered-file->buffer)
13273     #
13274     (write _test-input-stream "fn foo {\n")
13275     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
13276     (write _test-input-stream "  populate *y, 3\n")
13277     (write _test-input-stream "}\n")
13278     # convert
13279     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13280     (flush _test-output-buffered-file)
13281 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13287     # not bothering checking output
13288     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-deref-address: error message")
13289     # . epilogue
13290     5d/pop-to-ebp
13291     c3/return
13292 
13293 test-populate-stream-with-no-inout:
13294     # . prologue
13295     55/push-ebp
13296     89/<- %ebp 4/r32/esp
13297     # setup
13298     (clear-stream _test-input-stream)
13299     (clear-stream $_test-input-buffered-file->buffer)
13300     (clear-stream _test-output-stream)
13301     (clear-stream $_test-output-buffered-file->buffer)
13302     (clear-stream _test-error-stream)
13303     (clear-stream $_test-error-buffered-file->buffer)
13304     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13305     68/push 0/imm32
13306     68/push 0/imm32
13307     89/<- %edx 4/r32/esp
13308     (tailor-exit-descriptor %edx 0x10)
13309     #
13310     (write _test-input-stream "fn foo {\n")
13311     (write _test-input-stream "  populate-stream\n")
13312     (write _test-input-stream "}\n")
13313     # convert
13314     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13315     # registers except esp clobbered at this point
13316     # restore ed
13317     89/<- %edx 4/r32/esp
13318     (flush _test-output-buffered-file)
13319     (flush _test-error-buffered-file)
13320 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13326     # check output
13327     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
13328     (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")
13329     # check that stop(1) was called
13330     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
13331     # don't restore from ebp
13332     81 0/subop/add %esp 8/imm32
13333     # . epilogue
13334     5d/pop-to-ebp
13335     c3/return
13336 
13337 test-populate-stream-with-too-many-inouts:
13338     # . prologue
13339     55/push-ebp
13340     89/<- %ebp 4/r32/esp
13341     # setup
13342     (clear-stream _test-input-stream)
13343     (clear-stream $_test-input-buffered-file->buffer)
13344     (clear-stream _test-output-stream)
13345     (clear-stream $_test-output-buffered-file->buffer)
13346     (clear-stream _test-error-stream)
13347     (clear-stream $_test-error-buffered-file->buffer)
13348     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13349     68/push 0/imm32
13350     68/push 0/imm32
13351     89/<- %edx 4/r32/esp
13352     (tailor-exit-descriptor %edx 0x10)
13353     #
13354     (write _test-input-stream "fn foo {\n")
13355     (write _test-input-stream "  var x: (addr handle int)\n")
13356     (write _test-input-stream "  populate-stream x, 3, 0\n")
13357     (write _test-input-stream "}\n")
13358     # convert
13359     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13360     # registers except esp clobbered at this point
13361     # restore ed
13362     89/<- %edx 4/r32/esp
13363     (flush _test-output-buffered-file)
13364     (flush _test-error-buffered-file)
13365 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13371     # check output
13372     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
13373     (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")
13374     # check that stop(1) was called
13375     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
13376     # don't restore from ebp
13377     81 0/subop/add %esp 8/imm32
13378     # . epilogue
13379     5d/pop-to-ebp
13380     c3/return
13381 
13382 test-populate-stream-with-output:
13383     # . prologue
13384     55/push-ebp
13385     89/<- %ebp 4/r32/esp
13386     # setup
13387     (clear-stream _test-input-stream)
13388     (clear-stream $_test-input-buffered-file->buffer)
13389     (clear-stream _test-output-stream)
13390     (clear-stream $_test-output-buffered-file->buffer)
13391     (clear-stream _test-error-stream)
13392     (clear-stream $_test-error-buffered-file->buffer)
13393     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13394     68/push 0/imm32
13395     68/push 0/imm32
13396     89/<- %edx 4/r32/esp
13397     (tailor-exit-descriptor %edx 0x10)
13398     #
13399     (write _test-input-stream "fn foo {\n")
13400     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13401     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13402     (write _test-input-stream "  x <- populate-stream y\n")
13403     (write _test-input-stream "}\n")
13404     # convert
13405     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13406     # registers except esp clobbered at this point
13407     # restore ed
13408     89/<- %edx 4/r32/esp
13409     (flush _test-output-buffered-file)
13410     (flush _test-error-buffered-file)
13411 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13417     # check output
13418     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
13419     (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")
13420     # check that stop(1) was called
13421     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
13422     # don't restore from ebp
13423     81 0/subop/add %esp 8/imm32
13424     # . epilogue
13425     5d/pop-to-ebp
13426     c3/return
13427 
13428 test-populate-stream-non-addr:
13429     # . prologue
13430     55/push-ebp
13431     89/<- %ebp 4/r32/esp
13432     # setup
13433     (clear-stream _test-input-stream)
13434     (clear-stream $_test-input-buffered-file->buffer)
13435     (clear-stream _test-output-stream)
13436     (clear-stream $_test-output-buffered-file->buffer)
13437     (clear-stream _test-error-stream)
13438     (clear-stream $_test-error-buffered-file->buffer)
13439     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13440     68/push 0/imm32
13441     68/push 0/imm32
13442     89/<- %edx 4/r32/esp
13443     (tailor-exit-descriptor %edx 0x10)
13444     #
13445     (write _test-input-stream "fn foo {\n")
13446     (write _test-input-stream "  var y: (handle int)\n")
13447     (write _test-input-stream "  populate-stream y, 3\n")
13448     (write _test-input-stream "}\n")
13449     # convert
13450     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13451     # registers except esp clobbered at this point
13452     # restore ed
13453     89/<- %edx 4/r32/esp
13454     (flush _test-output-buffered-file)
13455     (flush _test-error-buffered-file)
13456 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13462     # check output
13463     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
13464     (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")
13465     # check that stop(1) was called
13466     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
13467     # don't restore from ebp
13468     81 0/subop/add %esp 8/imm32
13469     # . epilogue
13470     5d/pop-to-ebp
13471     c3/return
13472 
13473 test-populate-stream-non-addr-handle:
13474     # . prologue
13475     55/push-ebp
13476     89/<- %ebp 4/r32/esp
13477     # setup
13478     (clear-stream _test-input-stream)
13479     (clear-stream $_test-input-buffered-file->buffer)
13480     (clear-stream _test-output-stream)
13481     (clear-stream $_test-output-buffered-file->buffer)
13482     (clear-stream _test-error-stream)
13483     (clear-stream $_test-error-buffered-file->buffer)
13484     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13485     68/push 0/imm32
13486     68/push 0/imm32
13487     89/<- %edx 4/r32/esp
13488     (tailor-exit-descriptor %edx 0x10)
13489     #
13490     (write _test-input-stream "fn foo {\n")
13491     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13492     (write _test-input-stream "  populate-stream y, 3\n")
13493     (write _test-input-stream "}\n")
13494     # convert
13495     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13496     # registers except esp clobbered at this point
13497     # restore ed
13498     89/<- %edx 4/r32/esp
13499     (flush _test-output-buffered-file)
13500     (flush _test-error-buffered-file)
13501 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13507     # check output
13508     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
13509     (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")
13510     # check that stop(1) was called
13511     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
13512     # don't restore from ebp
13513     81 0/subop/add %esp 8/imm32
13514     # . epilogue
13515     5d/pop-to-ebp
13516     c3/return
13517 
13518 test-populate-stream-non-addr-handle-stream:
13519     # . prologue
13520     55/push-ebp
13521     89/<- %ebp 4/r32/esp
13522     # setup
13523     (clear-stream _test-input-stream)
13524     (clear-stream $_test-input-buffered-file->buffer)
13525     (clear-stream _test-output-stream)
13526     (clear-stream $_test-output-buffered-file->buffer)
13527     (clear-stream _test-error-stream)
13528     (clear-stream $_test-error-buffered-file->buffer)
13529     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13530     68/push 0/imm32
13531     68/push 0/imm32
13532     89/<- %edx 4/r32/esp
13533     (tailor-exit-descriptor %edx 0x10)
13534     #
13535     (write _test-input-stream "fn foo {\n")
13536     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13537     (write _test-input-stream "  populate-stream y, 3\n")
13538     (write _test-input-stream "}\n")
13539     # convert
13540     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13541     # registers except esp clobbered at this point
13542     # restore ed
13543     89/<- %edx 4/r32/esp
13544     (flush _test-output-buffered-file)
13545     (flush _test-error-buffered-file)
13546 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13552     # check output
13553     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
13554     (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")
13555     # check that stop(1) was called
13556     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
13557     # don't restore from ebp
13558     81 0/subop/add %esp 8/imm32
13559     # . epilogue
13560     5d/pop-to-ebp
13561     c3/return
13562 
13563 test-populate-stream-deref-address:
13564     # . prologue
13565     55/push-ebp
13566     89/<- %ebp 4/r32/esp
13567     # setup
13568     (clear-stream _test-input-stream)
13569     (clear-stream $_test-input-buffered-file->buffer)
13570     (clear-stream _test-output-stream)
13571     (clear-stream $_test-output-buffered-file->buffer)
13572     #
13573     (write _test-input-stream "fn foo {\n")
13574     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
13575     (write _test-input-stream "  populate-stream *y, 3\n")
13576     (write _test-input-stream "}\n")
13577     # convert
13578     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13579     (flush _test-output-buffered-file)
13580 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13586     # not bothering checking output
13587     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-stream-deref-address: error message")
13588     # . epilogue
13589     5d/pop-to-ebp
13590     c3/return
13591 
13592 #######################################################
13593 # Parsing
13594 #######################################################
13595 
13596 == data
13597 
13598 # Global state added to each var record when parsing a function
13599 Next-block-index:  # (addr int)
13600     1/imm32
13601 
13602 Curr-block-depth:  # (addr int)
13603     1/imm32
13604 
13605 == code
13606 
13607 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
13608     # pseudocode
13609     #   var curr-function: (addr handle function) = Program->functions
13610     #   var curr-signature: (addr handle function) = Program->signatures
13611     #   var curr-type: (addr handle typeinfo) = Program->types
13612     #   var line: (stream byte 512)
13613     #   var word-slice: slice
13614     #   while true                                  # line loop
13615     #     clear-stream(line)
13616     #     read-line-buffered(in, line)
13617     #     if (line->write == 0) break               # end of file
13618     #     word-slice = next-mu-token(line)
13619     #     if slice-empty?(word-slice)               # end of line
13620     #       continue
13621     #     else if slice-starts-with?(word-slice, "#")  # comment
13622     #       continue                                # end of line
13623     #     else if slice-equal?(word-slice, "fn")
13624     #       var new-function: (handle function) = allocate(function)
13625     #       var vars: (stack live-var 256)
13626     #       populate-mu-function-header(line, new-function, vars)
13627     #       populate-mu-function-body(in, new-function, vars)
13628     #       assert(vars->top == 0)
13629     #       *curr-function = new-function
13630     #       curr-function = &new-function->next
13631     #     else if slice-equal?(word-slice, "sig")
13632     #       var new-function: (handle function) = allocate(function)
13633     #       populate-mu-function-signature(line, new-function)
13634     #       *curr-signature = new-function
13635     #       curr-signature = &new-function->next
13636     #     else if slice-equal?(word-slice, "type")
13637     #       word-slice = next-mu-token(line)
13638     #       type-id = pos-or-insert-slice(Type-id, word-slice)
13639     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
13640     #       assert(next-word(line) == "{")
13641     #       populate-mu-type(in, new-type)
13642     #     else
13643     #       abort()
13644     #
13645     # . prologue
13646     55/push-ebp
13647     89/<- %ebp 4/r32/esp
13648     # var curr-signature: (addr handle function) at *(ebp-4)
13649     68/push _Program-signatures/imm32
13650     # . save registers
13651     50/push-eax
13652     51/push-ecx
13653     52/push-edx
13654     53/push-ebx
13655     56/push-esi
13656     57/push-edi
13657     # var line/ecx: (stream byte 512)
13658     81 5/subop/subtract %esp 0x200/imm32
13659     68/push 0x200/imm32/size
13660     68/push 0/imm32/read
13661     68/push 0/imm32/write
13662     89/<- %ecx 4/r32/esp
13663     # var word-slice/edx: slice
13664     68/push 0/imm32/end
13665     68/push 0/imm32/start
13666     89/<- %edx 4/r32/esp
13667     # var curr-function/edi: (addr handle function)
13668     bf/copy-to-edi _Program-functions/imm32
13669     # var vars/ebx: (stack live-var 256)
13670     81 5/subop/subtract %esp 0xc00/imm32
13671     68/push 0xc00/imm32/size
13672     68/push 0/imm32/top
13673     89/<- %ebx 4/r32/esp
13674     {
13675 $parse-mu:line-loop:
13676       (clear-stream %ecx)
13677       (read-line-buffered *(ebp+8) %ecx)
13678       # if (line->write == 0) break
13679       81 7/subop/compare *ecx 0/imm32
13680       0f 84/jump-if-= break/disp32
13681 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13687       (next-mu-token %ecx %edx)
13688       # if slice-empty?(word-slice) continue
13689       (slice-empty? %edx)  # => eax
13690       3d/compare-eax-and 0/imm32/false
13691       0f 85/jump-if-!= loop/disp32
13692       # if (*word-slice->start == "#") continue
13693       # . eax = *word-slice->start
13694       8b/-> *edx 0/r32/eax
13695       8a/copy-byte *eax 0/r32/AL
13696       81 4/subop/and %eax 0xff/imm32
13697       # . if (eax == '#') continue
13698       3d/compare-eax-and 0x23/imm32/hash
13699       0f 84/jump-if-= loop/disp32
13700       # if (slice-equal?(word-slice, "fn")) parse a function
13701       {
13702 $parse-mu:fn:
13703         (slice-equal? %edx "fn")  # => eax
13704         3d/compare-eax-and 0/imm32/false
13705         0f 84/jump-if-= break/disp32
13706         # var new-function/esi: (handle function)
13707         68/push 0/imm32
13708         68/push 0/imm32
13709         89/<- %esi 4/r32/esp
13710         # populate-mu-function(line, in, vars, new-function)
13711         (allocate Heap *Function-size %esi)
13712         # var new-function-addr/eax: (addr function)
13713         (lookup *esi *(esi+4))  # => eax
13714         # initialize vars
13715         (clear-stack %ebx)
13716         #
13717         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
13718         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
13719         # *curr-function = new-function
13720         8b/-> *esi 0/r32/eax
13721         89/<- *edi 0/r32/eax
13722         8b/-> *(esi+4) 0/r32/eax
13723         89/<- *(edi+4) 0/r32/eax
13724         # curr-function = &new-function->next
13725         # . var tmp/eax: (addr function) = lookup(new-function)
13726         (lookup *esi *(esi+4))  # => eax
13727         # . curr-function = &tmp->next
13728         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
13729         # reclaim new-function
13730         81 0/subop/add %esp 8/imm32
13731         #
13732         e9/jump $parse-mu:line-loop/disp32
13733       }
13734       # if (slice-equal?(word-slice, "sig")) parse a function signature
13735       # Function signatures are for providing types to SubX functions.
13736       {
13737 $parse-mu:sig:
13738         (slice-equal? %edx "sig")  # => eax
13739         3d/compare-eax-and 0/imm32/false
13740         0f 84/jump-if-= break/disp32
13741         # edi = curr-function
13742         57/push-edi
13743         8b/-> *(ebp-4) 7/r32/edi
13744         # var new-function/esi: (handle function)
13745         68/push 0/imm32
13746         68/push 0/imm32
13747         89/<- %esi 4/r32/esp
13748         # populate-mu-function(line, in, vars, new-function)
13749         (allocate Heap *Function-size %esi)
13750         # var new-function-addr/eax: (addr function)
13751         (lookup *esi *(esi+4))  # => eax
13752         #
13753         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
13754         # *curr-signature = new-function
13755         8b/-> *esi 0/r32/eax
13756         89/<- *edi 0/r32/eax
13757         8b/-> *(esi+4) 0/r32/eax
13758         89/<- *(edi+4) 0/r32/eax
13759         # curr-signature = &new-function->next
13760         # . var tmp/eax: (addr function) = lookup(new-function)
13761         (lookup *esi *(esi+4))  # => eax
13762         # . curr-function = &tmp->next
13763         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
13764         # reclaim new-function
13765         81 0/subop/add %esp 8/imm32
13766         # save curr-function
13767         89/<- *(ebp-4) 7/r32/edi
13768         # restore edi
13769         5f/pop-to-edi
13770         #
13771         e9/jump $parse-mu:line-loop/disp32
13772       }
13773       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
13774       {
13775 $parse-mu:type:
13776         (slice-equal? %edx "type")  # => eax
13777         3d/compare-eax-and 0/imm32
13778         0f 84/jump-if-= break/disp32
13779         (next-mu-token %ecx %edx)
13780         # var type-id/eax: int
13781         (pos-or-insert-slice Type-id %edx)  # => eax
13782         # spill
13783         51/push-ecx
13784         # var new-type/ecx: (handle typeinfo)
13785         68/push 0/imm32
13786         68/push 0/imm32
13787         89/<- %ecx 4/r32/esp
13788         (find-or-create-typeinfo %eax %ecx)
13789         #
13790         (lookup *ecx *(ecx+4))  # => eax
13791         # TODO: ensure that 'line' has nothing else but '{'
13792 #? (dump-typeinfos "=== aaa\n")
13793         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
13794 #? (dump-typeinfos "=== zzz\n")
13795         # reclaim new-type
13796         81 0/subop/add %esp 8/imm32
13797         # restore
13798         59/pop-to-ecx
13799         e9/jump $parse-mu:line-loop/disp32
13800       }
13801       # otherwise abort
13802       e9/jump $parse-mu:error1/disp32
13803     } # end line loop
13804 $parse-mu:end:
13805     # . reclaim locals
13806     81 0/subop/add %esp 0x20c/imm32  # line
13807     81 0/subop/add %esp 0xc08/imm32  # vars
13808     81 0/subop/add %esp 8/imm32
13809     # . restore registers
13810     5f/pop-to-edi
13811     5e/pop-to-esi
13812     5b/pop-to-ebx
13813     5a/pop-to-edx
13814     59/pop-to-ecx
13815     58/pop-to-eax
13816     # . reclaim local
13817     81 0/subop/add %esp 4/imm32
13818     # . epilogue
13819     89/<- %esp 5/r32/ebp
13820     5d/pop-to-ebp
13821     c3/return
13822 
13823 $parse-mu:error1:
13824     # error("unexpected top-level command: " word-slice "\n")
13825     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
13826     (write-slice-buffered *(ebp+0xc) %edx)
13827     (write-buffered *(ebp+0xc) "\n")
13828     (flush *(ebp+0xc))
13829     (stop *(ebp+0x10) 1)
13830     # never gets here
13831 
13832 $parse-mu:error2:
13833     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
13834     (write-int32-hex-buffered *(ebp+0xc) *ebx)
13835     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
13836     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
13837     (write-buffered *(ebp+0xc) "'\n")
13838     (flush *(ebp+0xc))
13839     (stop *(ebp+0x10) 1)
13840     # never gets here
13841 
13842 # scenarios considered:
13843 # ✗ fn foo  # no block
13844 # ✓ fn foo {
13845 # ✗ fn foo { {
13846 # ✗ fn foo { }
13847 # ✗ fn foo { } {
13848 # ✗ fn foo x {
13849 # ✗ fn foo x: {
13850 # ✓ fn foo x: int {
13851 # ✓ fn foo x: int {
13852 # ✓ fn foo x: int -> _/eax: int {
13853 # TODO:
13854 #   disallow outputs of type `(... addr ...)`
13855 #   disallow inputs of type `(... addr ... addr ...)`
13856 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)
13857     # pseudocode:
13858     #   var word-slice: slice
13859     #   next-mu-token(first-line, word-slice)
13860     #   if slice-empty?(word-slice) abort
13861     #   assert(word-slice not in '{' '}' '->')
13862     #   out->name = slice-to-string(word-slice)
13863     #   ## inouts
13864     #   while true
13865     #     word-slice = next-mu-token(first-line)
13866     #     if slice-empty?(word-slice) abort
13867     #     if (word-slice == '{') goto done
13868     #     if (word-slice == '->') break
13869     #     assert(word-slice != '}')
13870     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
13871     #     assert(v->register == null)
13872     #     # v->block-depth is implicitly 0
13873     #     out->inouts = append(v, out->inouts)
13874     #     push(vars, {v, false})
13875     #   ## outputs
13876     #   while true
13877     #     word-slice = next-mu-token(first-line)
13878     #     if slice-empty?(word-slice) abort
13879     #     if (word-slice == '{') break
13880     #     assert(word-slice not in '}' '->')
13881     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
13882     #     assert(v->register != null)
13883     #     assert(v->name == "_")
13884     #     out->outputs = append(v, out->outputs)
13885     #   done:
13886     #
13887     # . prologue
13888     55/push-ebp
13889     89/<- %ebp 4/r32/esp
13890     # . save registers
13891     50/push-eax
13892     51/push-ecx
13893     52/push-edx
13894     53/push-ebx
13895     57/push-edi
13896     # edi = out
13897     8b/-> *(ebp+0xc) 7/r32/edi
13898     # var word-slice/ecx: slice
13899     68/push 0/imm32/end
13900     68/push 0/imm32/start
13901     89/<- %ecx 4/r32/esp
13902     # var v/ebx: (handle var)
13903     68/push 0/imm32
13904     68/push 0/imm32
13905     89/<- %ebx 4/r32/esp
13906     # read function name
13907     (next-mu-token *(ebp+8) %ecx)
13908     # error checking
13909     # if slice-empty?(word-slice) abort
13910     (slice-empty? %ecx)  # => eax
13911     3d/compare-eax-and 0/imm32/false
13912     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13913     # if (word-slice == '{') abort
13914     (slice-equal? %ecx "{")   # => eax
13915     3d/compare-eax-and 0/imm32/false
13916     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13917     # if (word-slice == '->') abort
13918     (slice-equal? %ecx "->")   # => eax
13919     3d/compare-eax-and 0/imm32/false
13920     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13921     # if (word-slice == '}') abort
13922     (slice-equal? %ecx "}")   # => eax
13923     3d/compare-eax-and 0/imm32/false
13924     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13925     # if word-slice already defined, abort
13926     (function-exists? %ecx)  # => eax
13927     3d/compare-eax-and 0/imm32/false
13928     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
13929     #
13930     (slice-starts-with? %ecx "break")  # => eax
13931     3d/compare-eax-and 0/imm32/false
13932     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
13933     (slice-starts-with? %ecx "loop")  # => eax
13934     3d/compare-eax-and 0/imm32/false
13935     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
13936     # save function name
13937     (slice-to-string Heap %ecx %edi)  # Function-name
13938     # save function inouts
13939     {
13940 $populate-mu-function-header:check-for-inout:
13941       (next-mu-token *(ebp+8) %ecx)
13942       # if slice-empty?(word-slice) abort
13943       (slice-empty? %ecx)  # => eax
13944       3d/compare-eax-and 0/imm32/false
13945       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13946       # if (word-slice == '{') goto done
13947       (slice-equal? %ecx "{")   # => eax
13948       3d/compare-eax-and 0/imm32/false
13949       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
13950       # if (word-slice == '->') break
13951       (slice-equal? %ecx "->")   # => eax
13952       3d/compare-eax-and 0/imm32/false
13953       0f 85/jump-if-!= break/disp32
13954       # if (word-slice == '}') abort
13955       (slice-equal? %ecx "}")   # => eax
13956       3d/compare-eax-and 0/imm32/false
13957       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13958       # v = parse-var-with-type(word-slice, first-line)
13959       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
13960       # assert(v->register == null)
13961       # . eax: (addr var) = lookup(v)
13962       (lookup *ebx *(ebx+4))  # => eax
13963       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
13964       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
13965       # v->block-depth is implicitly 0
13966       #
13967       # out->inouts = append(v, out->inouts)
13968       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
13969       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
13970       # push(vars, {v, false})
13971       (push *(ebp+0x10) *ebx)
13972       (push *(ebp+0x10) *(ebx+4))
13973       (push *(ebp+0x10) 0)  # false
13974       #
13975       e9/jump loop/disp32
13976     }
13977     # save function outputs
13978     {
13979 $populate-mu-function-header:check-for-out:
13980       (next-mu-token *(ebp+8) %ecx)
13981       # if slice-empty?(word-slice) abort
13982       (slice-empty? %ecx)  # => eax
13983       3d/compare-eax-and 0/imm32/false
13984       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13985       # if (word-slice == '{') break
13986       (slice-equal? %ecx "{")   # => eax
13987       3d/compare-eax-and 0/imm32/false
13988       0f 85/jump-if-!= break/disp32
13989       # if (word-slice == '->') abort
13990       (slice-equal? %ecx "->")   # => eax
13991       3d/compare-eax-and 0/imm32/false
13992       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13993       # if (word-slice == '}') abort
13994       (slice-equal? %ecx "}")   # => eax
13995       3d/compare-eax-and 0/imm32/false
13996       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
13997       # v = parse-var-with-type(word-slice, first-line)
13998       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
13999       # assert(var->register != null)
14000       # . eax: (addr var) = lookup(v)
14001       (lookup *ebx *(ebx+4))  # => eax
14002       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14003       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
14004       # assert(var->name == "_")
14005       (lookup *eax *(eax+4))  # Var-name Var-name => eax
14006       (string-equal? %eax "_")  # => eax
14007       3d/compare-eax-and 0/imm32/false
14008       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
14009       # out->outputs = append(v, out->outputs)
14010       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
14011       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
14012       #
14013       e9/jump loop/disp32
14014     }
14015 $populate-mu-function-header:done:
14016     (check-no-tokens-left *(ebp+8))
14017 $populate-mu-function-header:end:
14018     # . reclaim locals
14019     81 0/subop/add %esp 0x10/imm32
14020     # . restore registers
14021     5f/pop-to-edi
14022     5b/pop-to-ebx
14023     5a/pop-to-edx
14024     59/pop-to-ecx
14025     58/pop-to-eax
14026     # . epilogue
14027     89/<- %esp 5/r32/ebp
14028     5d/pop-to-ebp
14029     c3/return
14030 
14031 $populate-mu-function-header:error1:
14032     # error("function header not in form 'fn <name> {'")
14033     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
14034     (flush *(ebp+0x14))
14035     (rewind-stream *(ebp+8))
14036     (write-stream-data *(ebp+0x14) *(ebp+8))
14037     (write-buffered *(ebp+0x14) "'\n")
14038     (flush *(ebp+0x14))
14039     (stop *(ebp+0x18) 1)
14040     # never gets here
14041 
14042 $populate-mu-function-header:error2:
14043     # error("fn " fn ": function inout '" var "' cannot be in a register")
14044     (write-buffered *(ebp+0x14) "fn ")
14045     50/push-eax
14046     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14047     (write-buffered *(ebp+0x14) %eax)
14048     58/pop-to-eax
14049     (write-buffered *(ebp+0x14) ": function inout '")
14050     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14051     (write-buffered *(ebp+0x14) %eax)
14052     (write-buffered *(ebp+0x14) "' cannot be in a register")
14053     (flush *(ebp+0x14))
14054     (stop *(ebp+0x18) 1)
14055     # never gets here
14056 
14057 $populate-mu-function-header:error3:
14058     # error("fn " fn ": function output '" var "' must be in a register")
14059     (write-buffered *(ebp+0x14) "fn ")
14060     50/push-eax
14061     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14062     (write-buffered *(ebp+0x14) %eax)
14063     58/pop-to-eax
14064     (write-buffered *(ebp+0x14) ": function output '")
14065     (lookup *ebx *(ebx+4))  # => eax
14066     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14067     (write-buffered *(ebp+0x14) %eax)
14068     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
14069     (rewind-stream *(ebp+8))
14070     (write-stream-data *(ebp+0x14) *(ebp+8))
14071     (write-buffered *(ebp+0x14) "'\n")
14072     (flush *(ebp+0x14))
14073     (stop *(ebp+0x18) 1)
14074     # never gets here
14075 
14076 $populate-mu-function-header:error4:
14077     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
14078     (write-buffered *(ebp+0x14) "fn ")
14079     50/push-eax
14080     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14081     (write-buffered *(ebp+0x14) %eax)
14082     58/pop-to-eax
14083     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
14084     (lookup *ebx *(ebx+4))  # => eax
14085     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14086     (write-buffered *(ebp+0x14) %eax)
14087     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
14088     (flush *(ebp+0x14))
14089     (stop *(ebp+0x18) 1)
14090     # never gets here
14091 
14092 $populate-mu-function-header:error-duplicate:
14093     (write-buffered *(ebp+0x14) "fn ")
14094     (write-slice-buffered *(ebp+0x14) %ecx)
14095     (write-buffered *(ebp+0x14) " defined more than once\n")
14096     (flush *(ebp+0x14))
14097     (stop *(ebp+0x18) 1)
14098     # never gets here
14099 
14100 $populate-mu-function-header:error-break:
14101     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
14102     (flush *(ebp+0x14))
14103     (stop *(ebp+0x18) 1)
14104     # never gets here
14105 
14106 $populate-mu-function-header:error-loop:
14107     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
14108     (flush *(ebp+0x14))
14109     (stop *(ebp+0x18) 1)
14110     # never gets here
14111 
14112 # scenarios considered:
14113 # ✓ fn foo
14114 # ✗ fn foo {
14115 # ✓ fn foo x
14116 # ✓ fn foo x: int
14117 # ✓ fn foo x: int -> _/eax: int
14118 # TODO:
14119 #   disallow outputs of type `(... addr ...)`
14120 #   disallow inputs of type `(... addr ... addr ...)`
14121 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14122     # pseudocode:
14123     #   var word-slice: slice
14124     #   next-mu-token(first-line, word-slice)
14125     #   assert(word-slice not in '{' '}' '->')
14126     #   out->name = slice-to-string(word-slice)
14127     #   ## inouts
14128     #   while true
14129     #     word-slice = next-mu-token(first-line)
14130     #     if slice-empty?(word-slice) break
14131     #     if (word-slice == '->') break
14132     #     assert(word-slice not in '{' '}')
14133     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14134     #     assert(v->register == null)
14135     #     # v->block-depth is implicitly 0
14136     #     out->inouts = append(v, out->inouts)
14137     #   ## outputs
14138     #   while true
14139     #     word-slice = next-mu-token(first-line)
14140     #     if slice-empty?(word-slice) break
14141     #     assert(word-slice not in '{' '}' '->')
14142     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14143     #     assert(v->register != null)
14144     #     out->outputs = append(v, out->outputs)
14145     #
14146     # . prologue
14147     55/push-ebp
14148     89/<- %ebp 4/r32/esp
14149     # . save registers
14150     50/push-eax
14151     51/push-ecx
14152     52/push-edx
14153     53/push-ebx
14154     57/push-edi
14155     # edi = out
14156     8b/-> *(ebp+0xc) 7/r32/edi
14157     # var word-slice/ecx: slice
14158     68/push 0/imm32/end
14159     68/push 0/imm32/start
14160     89/<- %ecx 4/r32/esp
14161     # var v/ebx: (handle var)
14162     68/push 0/imm32
14163     68/push 0/imm32
14164     89/<- %ebx 4/r32/esp
14165     # read function name
14166     (next-mu-token *(ebp+8) %ecx)
14167     # error checking
14168     # if (word-slice == '{') abort
14169     (slice-equal? %ecx "{")   # => eax
14170     3d/compare-eax-and 0/imm32/false
14171     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14172     # if (word-slice == '->') abort
14173     (slice-equal? %ecx "->")   # => eax
14174     3d/compare-eax-and 0/imm32/false
14175     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14176     # if (word-slice == '}') abort
14177     (slice-equal? %ecx "}")   # => eax
14178     3d/compare-eax-and 0/imm32/false
14179     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14180     # if word-slice already defined, abort
14181     (function-exists? %ecx)  # => eax
14182     3d/compare-eax-and 0/imm32/false
14183     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
14184     #
14185     (slice-starts-with? %ecx "break")  # => eax
14186     3d/compare-eax-and 0/imm32/false
14187     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
14188     (slice-starts-with? %ecx "loop")  # => eax
14189     3d/compare-eax-and 0/imm32/false
14190     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
14191     # save function name
14192     (slice-to-string Heap %ecx %edi)  # Function-name
14193     # save function inouts
14194     {
14195 $populate-mu-function-signature:check-for-inout:
14196       (next-mu-token *(ebp+8) %ecx)
14197       (slice-empty? %ecx)  # => eax
14198       3d/compare-eax-and 0/imm32/false
14199       0f 85/jump-if-!= break/disp32
14200       # if (word-slice == '->') break
14201       (slice-equal? %ecx "->")   # => eax
14202       3d/compare-eax-and 0/imm32/false
14203       0f 85/jump-if-!= break/disp32
14204       # if (word-slice == '{') abort
14205       (slice-equal? %ecx "{")   # => eax
14206       3d/compare-eax-and 0/imm32/false
14207       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14208       # if (word-slice == '}') abort
14209       (slice-equal? %ecx "}")   # => eax
14210       3d/compare-eax-and 0/imm32/false
14211       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14212       # v = parse-var-with-type(word-slice, first-line)
14213       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
14214       # assert(v->register == null)
14215       # . eax: (addr var) = lookup(v)
14216       (lookup *ebx *(ebx+4))  # => eax
14217       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14218       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
14219       # v->block-depth is implicitly 0
14220       #
14221       # out->inouts = append(v, out->inouts)
14222       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
14223       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
14224       #
14225       e9/jump loop/disp32
14226     }
14227     # save function outputs
14228     {
14229 $populate-mu-function-signature:check-for-out:
14230       (next-mu-token *(ebp+8) %ecx)
14231       (slice-empty? %ecx)  # => eax
14232       3d/compare-eax-and 0/imm32/false
14233       0f 85/jump-if-!= break/disp32
14234       # if (word-slice == '{') abort
14235       (slice-equal? %ecx "{")   # => eax
14236       3d/compare-eax-and 0/imm32/false
14237       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14238       # if (word-slice == '->') abort
14239       (slice-equal? %ecx "->")   # => eax
14240       3d/compare-eax-and 0/imm32/false
14241       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14242       # if (word-slice == '}') abort
14243       (slice-equal? %ecx "}")   # => eax
14244       3d/compare-eax-and 0/imm32/false
14245       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14246       # v = parse-var-with-type(word-slice, first-line)
14247       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
14248       # assert(var->register != null)
14249       # . eax: (addr var) = lookup(v)
14250       (lookup *ebx *(ebx+4))  # => eax
14251       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14252       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
14253       # out->outputs = append(v, out->outputs)
14254       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
14255       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
14256       #
14257       e9/jump loop/disp32
14258     }
14259 $populate-mu-function-signature:done:
14260     (check-no-tokens-left *(ebp+8))
14261 $populate-mu-function-signature:end:
14262     # . reclaim locals
14263     81 0/subop/add %esp 0x10/imm32
14264     # . restore registers
14265     5f/pop-to-edi
14266     5b/pop-to-ebx
14267     5a/pop-to-edx
14268     59/pop-to-ecx
14269     58/pop-to-eax
14270     # . epilogue
14271     89/<- %esp 5/r32/ebp
14272     5d/pop-to-ebp
14273     c3/return
14274 
14275 $populate-mu-function-signature:error1:
14276     # error("function signature not in form 'fn <name> {'")
14277     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
14278     (flush *(ebp+0x10))
14279     (rewind-stream *(ebp+8))
14280     (write-stream-data *(ebp+0x10) *(ebp+8))
14281     (write-buffered *(ebp+0x10) "'\n")
14282     (flush *(ebp+0x10))
14283     (stop *(ebp+0x14) 1)
14284     # never gets here
14285 
14286 $populate-mu-function-signature:error2:
14287     # error("fn " fn ": function inout '" var "' cannot be in a register")
14288     (write-buffered *(ebp+0x10) "fn ")
14289     50/push-eax
14290     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14291     (write-buffered *(ebp+0x10) %eax)
14292     58/pop-to-eax
14293     (write-buffered *(ebp+0x10) ": function inout '")
14294     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14295     (write-buffered *(ebp+0x10) %eax)
14296     (write-buffered *(ebp+0x10) "' cannot be in a register")
14297     (flush *(ebp+0x10))
14298     (stop *(ebp+0x14) 1)
14299     # never gets here
14300 
14301 $populate-mu-function-signature:error3:
14302     # error("fn " fn ": function output '" var "' must be in a register")
14303     (write-buffered *(ebp+0x10) "fn ")
14304     50/push-eax
14305     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14306     (write-buffered *(ebp+0x10) %eax)
14307     58/pop-to-eax
14308     (write-buffered *(ebp+0x10) ": function output '")
14309     (lookup *ebx *(ebx+4))  # => eax
14310     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14311     (write-buffered *(ebp+0x10) %eax)
14312     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
14313     (rewind-stream *(ebp+8))
14314     (write-stream-data *(ebp+0x10) *(ebp+8))
14315     (write-buffered *(ebp+0x10) "'\n")
14316     (flush *(ebp+0x10))
14317     (stop *(ebp+0x14) 1)
14318     # never gets here
14319 
14320 $populate-mu-function-signature:error-duplicate:
14321     (write-buffered *(ebp+0x10) "fn ")
14322     (write-slice-buffered *(ebp+0x10) %ecx)
14323     (write-buffered *(ebp+0x10) " defined more than once\n")
14324     (flush *(ebp+0x10))
14325     (stop *(ebp+0x14) 1)
14326     # never gets here
14327 
14328 $populate-mu-function-signature:error-break:
14329     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
14330     (flush *(ebp+0x14))
14331     (stop *(ebp+0x18) 1)
14332     # never gets here
14333 
14334 $populate-mu-function-signature:error-loop:
14335     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
14336     (flush *(ebp+0x14))
14337     (stop *(ebp+0x18) 1)
14338     # never gets here
14339 
14340 function-exists?:  # s: (addr slice) -> result/eax: boolean
14341     # . prologue
14342     55/push-ebp
14343     89/<- %ebp 4/r32/esp
14344     # . save registers
14345     51/push-ecx
14346     # var curr/ecx: (addr function) = functions
14347     (lookup *_Program-functions *_Program-functions->payload)  # => eax
14348     89/<- %ecx 0/r32/eax
14349     {
14350       # if (curr == null) break
14351       81 7/subop/compare %ecx 0/imm32
14352       74/jump-if-= break/disp8
14353       # if (curr->name == s) return true
14354       {
14355         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
14356         (slice-equal? *(ebp+8) %eax)  # => eax
14357         3d/compare-eax-and 0/imm32/false
14358         74/jump-if-= break/disp8
14359         b8/copy-to-eax 1/imm32/true
14360         e9/jump $function-exists?:end/disp32
14361       }
14362       # curr = curr->next
14363       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
14364       89/<- %ecx 0/r32/eax
14365       #
14366       eb/jump loop/disp8
14367     }
14368     # var curr/ecx: (addr function) = signatures
14369     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
14370     89/<- %ecx 0/r32/eax
14371     {
14372       # if (curr == null) break
14373       81 7/subop/compare %ecx 0/imm32
14374       74/jump-if-= break/disp8
14375       # if (curr->name == s) return true
14376       {
14377         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
14378         (slice-equal? *(ebp+8) %eax)  # => eax
14379         3d/compare-eax-and 0/imm32/false
14380         74/jump-if-= break/disp8
14381         b8/copy-to-eax 1/imm32/true
14382         eb/jump $function-exists?:end/disp8
14383       }
14384       # curr = curr->next
14385       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
14386       89/<- %ecx 0/r32/eax
14387       #
14388       eb/jump loop/disp8
14389     }
14390     # return false
14391     b8/copy-to-eax 0/imm32/false
14392 $function-exists?:end:
14393     # . restore registers
14394     59/pop-to-ecx
14395     # . epilogue
14396     89/<- %esp 5/r32/ebp
14397     5d/pop-to-ebp
14398     c3/return
14399 
14400 test-function-header-with-arg:
14401     # . prologue
14402     55/push-ebp
14403     89/<- %ebp 4/r32/esp
14404     # setup
14405     8b/-> *Primitive-type-ids 0/r32/eax
14406     89/<- *Type-id 0/r32/eax  # stream-write
14407     c7 0/subop/copy *_Program-functions 0/imm32
14408     c7 0/subop/copy *_Program-functions->payload 0/imm32
14409     c7 0/subop/copy *_Program-types 0/imm32
14410     c7 0/subop/copy *_Program-types->payload 0/imm32
14411     c7 0/subop/copy *_Program-signatures 0/imm32
14412     c7 0/subop/copy *_Program-signatures->payload 0/imm32
14413     (clear-stream _test-input-stream)
14414     (write _test-input-stream "foo n: int {\n")
14415     # var result/ecx: function
14416     2b/subtract *Function-size 4/r32/esp
14417     89/<- %ecx 4/r32/esp
14418     (zero-out %ecx *Function-size)
14419     # var vars/ebx: (stack live-var 16)
14420     81 5/subop/subtract %esp 0xc0/imm32
14421     68/push 0xc0/imm32/size
14422     68/push 0/imm32/top
14423     89/<- %ebx 4/r32/esp
14424     # convert
14425     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
14426     # check result->name
14427     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
14428     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
14429     # var v/edx: (addr var) = result->inouts->value
14430     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
14431     (lookup *eax *(eax+4))  # List-value List-value => eax
14432     89/<- %edx 0/r32/eax
14433     # check v->name
14434     (lookup *edx *(edx+4))  # Var-name Var-name => eax
14435     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
14436     # check v->type
14437     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
14438     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
14439     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
14440     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
14441     # . epilogue
14442     89/<- %esp 5/r32/ebp
14443     5d/pop-to-ebp
14444     c3/return
14445 
14446 test-function-header-with-multiple-args:
14447     # . prologue
14448     55/push-ebp
14449     89/<- %ebp 4/r32/esp
14450     # setup
14451     8b/-> *Primitive-type-ids 0/r32/eax
14452     89/<- *Type-id 0/r32/eax  # stream-write
14453     c7 0/subop/copy *_Program-functions 0/imm32
14454     c7 0/subop/copy *_Program-functions->payload 0/imm32
14455     c7 0/subop/copy *_Program-types 0/imm32
14456     c7 0/subop/copy *_Program-types->payload 0/imm32
14457     c7 0/subop/copy *_Program-signatures 0/imm32
14458     c7 0/subop/copy *_Program-signatures->payload 0/imm32
14459     (clear-stream _test-input-stream)
14460     (write _test-input-stream "foo a: int, b: int c: int {\n")
14461     # result/ecx: function
14462     2b/subtract *Function-size 4/r32/esp
14463     89/<- %ecx 4/r32/esp
14464     (zero-out %ecx *Function-size)
14465     # var vars/ebx: (stack live-var 16)
14466     81 5/subop/subtract %esp 0xc0/imm32
14467     68/push 0xc0/imm32/size
14468     68/push 0/imm32/top
14469     89/<- %ebx 4/r32/esp
14470     # convert
14471     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
14472     # check result->name
14473     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
14474     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
14475     # var inouts/edx: (addr list var) = lookup(result->inouts)
14476     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
14477     89/<- %edx 0/r32/eax
14478 $test-function-header-with-multiple-args:inout0:
14479     # var v/ebx: (addr var) = lookup(inouts->value)
14480     (lookup *edx *(edx+4))  # List-value List-value => eax
14481     89/<- %ebx 0/r32/eax
14482     # check v->name
14483     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14484     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
14485     # check v->type
14486     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14487     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
14488     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
14489     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
14490 $test-function-header-with-multiple-args:inout1:
14491     # inouts = lookup(inouts->next)
14492     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14493     89/<- %edx 0/r32/eax
14494     # v = lookup(inouts->value)
14495     (lookup *edx *(edx+4))  # List-value List-value => eax
14496     89/<- %ebx 0/r32/eax
14497     # check v->name
14498     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14499     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
14500     # check v->type
14501     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14502     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
14503     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
14504     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
14505 $test-function-header-with-multiple-args:inout2:
14506     # inouts = lookup(inouts->next)
14507     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14508     89/<- %edx 0/r32/eax
14509     # v = lookup(inouts->value)
14510     (lookup *edx *(edx+4))  # List-value List-value => eax
14511     89/<- %ebx 0/r32/eax
14512     # check v->name
14513     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14514     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
14515     # check v->type
14516     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14517     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
14518     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
14519     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
14520     # . epilogue
14521     89/<- %esp 5/r32/ebp
14522     5d/pop-to-ebp
14523     c3/return
14524 
14525 test-function-header-with-multiple-args-and-outputs:
14526     # . prologue
14527     55/push-ebp
14528     89/<- %ebp 4/r32/esp
14529     # setup
14530     8b/-> *Primitive-type-ids 0/r32/eax
14531     89/<- *Type-id 0/r32/eax  # stream-write
14532     c7 0/subop/copy *_Program-functions 0/imm32
14533     c7 0/subop/copy *_Program-functions->payload 0/imm32
14534     c7 0/subop/copy *_Program-types 0/imm32
14535     c7 0/subop/copy *_Program-types->payload 0/imm32
14536     c7 0/subop/copy *_Program-signatures 0/imm32
14537     c7 0/subop/copy *_Program-signatures->payload 0/imm32
14538     (clear-stream _test-input-stream)
14539     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
14540     # result/ecx: function
14541     2b/subtract *Function-size 4/r32/esp
14542     89/<- %ecx 4/r32/esp
14543     (zero-out %ecx *Function-size)
14544     # var vars/ebx: (stack live-var 16)
14545     81 5/subop/subtract %esp 0xc0/imm32
14546     68/push 0xc0/imm32/size
14547     68/push 0/imm32/top
14548     89/<- %ebx 4/r32/esp
14549     # convert
14550     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
14551     # check result->name
14552     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
14553     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
14554     # var inouts/edx: (addr list var) = lookup(result->inouts)
14555     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
14556     89/<- %edx 0/r32/eax
14557 $test-function-header-with-multiple-args-and-outputs:inout0:
14558     # var v/ebx: (addr var) = lookup(inouts->value)
14559     (lookup *edx *(edx+4))  # List-value List-value => eax
14560     89/<- %ebx 0/r32/eax
14561     # check v->name
14562     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14563     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
14564     # check v->type
14565     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14566     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
14567     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
14568     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
14569 $test-function-header-with-multiple-args-and-outputs:inout1:
14570     # inouts = lookup(inouts->next)
14571     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14572     89/<- %edx 0/r32/eax
14573     # v = lookup(inouts->value)
14574     (lookup *edx *(edx+4))  # List-value List-value => eax
14575     89/<- %ebx 0/r32/eax
14576     # check v->name
14577     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14578     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
14579     # check v->type
14580     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14581     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
14582     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
14583     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
14584 $test-function-header-with-multiple-args-and-outputs:inout2:
14585     # inouts = lookup(inouts->next)
14586     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14587     89/<- %edx 0/r32/eax
14588     # v = lookup(inouts->value)
14589     (lookup *edx *(edx+4))  # List-value List-value => eax
14590     89/<- %ebx 0/r32/eax
14591     # check v->name
14592     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14593     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
14594     # check v->type
14595     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14596     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
14597     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
14598     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
14599 $test-function-header-with-multiple-args-and-outputs:out0:
14600     # var outputs/edx: (addr list var) = lookup(result->outputs)
14601     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
14602     89/<- %edx 0/r32/eax
14603     # v = lookup(outputs->value)
14604     (lookup *edx *(edx+4))  # List-value List-value => eax
14605     89/<- %ebx 0/r32/eax
14606     # check v->name
14607     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14608     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
14609     # check v->register
14610     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
14611     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
14612     # check v->type
14613     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14614     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
14615     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
14616     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
14617 $test-function-header-with-multiple-args-and-outputs:out1:
14618     # outputs = lookup(outputs->next)
14619     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14620     89/<- %edx 0/r32/eax
14621     # v = lookup(inouts->value)
14622     (lookup *edx *(edx+4))  # List-value List-value => eax
14623     89/<- %ebx 0/r32/eax
14624     # check v->name
14625     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
14626     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
14627     # check v->register
14628     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
14629     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
14630     # check v->type
14631     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
14632     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
14633     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
14634     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
14635     # . epilogue
14636     89/<- %esp 5/r32/ebp
14637     5d/pop-to-ebp
14638     c3/return
14639 
14640 # format for variables with types
14641 #   x: int
14642 #   x: int,
14643 #   x/eax: int
14644 #   x/eax: int,
14645 # ignores at most one trailing comma
14646 # WARNING: modifies name
14647 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
14648     # pseudocode:
14649     #   var s: slice
14650     #   if (!slice-ends-with(name, ":"))
14651     #     abort
14652     #   --name->end to skip ':'
14653     #   next-token-from-slice(name->start, name->end, '/', s)
14654     #   new-var-from-slice(s, out)
14655     #   ## register
14656     #   next-token-from-slice(s->end, name->end, '/', s)
14657     #   if (!slice-empty?(s))
14658     #     out->register = slice-to-string(s)
14659     #   ## type
14660     #   var type: (handle type-tree) = parse-type(first-line)
14661     #   out->type = type
14662     #
14663     # . prologue
14664     55/push-ebp
14665     89/<- %ebp 4/r32/esp
14666     # . save registers
14667     50/push-eax
14668     51/push-ecx
14669     52/push-edx
14670     53/push-ebx
14671     56/push-esi
14672     57/push-edi
14673     # esi = name
14674     8b/-> *(ebp+8) 6/r32/esi
14675     # if (!slice-ends-with?(name, ":")) abort
14676     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
14677     49/decrement-ecx
14678     8a/copy-byte *ecx 1/r32/CL
14679     81 4/subop/and %ecx 0xff/imm32
14680     81 7/subop/compare %ecx 0x3a/imm32/colon
14681     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
14682     # --name->end to skip ':'
14683     ff 1/subop/decrement *(esi+4)
14684     # var s/ecx: slice
14685     68/push 0/imm32/end
14686     68/push 0/imm32/start
14687     89/<- %ecx 4/r32/esp
14688 $parse-var-with-type:parse-name:
14689     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
14690 $parse-var-with-type:create-var:
14691     # new-var-from-slice(s, out)
14692     (new-var-from-slice Heap %ecx *(ebp+0x10))
14693     # save out->register
14694 $parse-var-with-type:save-register:
14695     # . var out-addr/edi: (addr var) = lookup(*out)
14696     8b/-> *(ebp+0x10) 7/r32/edi
14697     (lookup *edi *(edi+4))  # => eax
14698     89/<- %edi 0/r32/eax
14699     # . s = next-token(...)
14700     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
14701     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
14702     {
14703 $parse-var-with-type:write-register:
14704       (slice-empty? %ecx)  # => eax
14705       3d/compare-eax-and 0/imm32/false
14706       75/jump-if-!= break/disp8
14707       # out->register = slice-to-string(s)
14708       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
14709       (slice-to-string Heap %ecx %eax)
14710     }
14711 $parse-var-with-type:save-type:
14712     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
14713     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14714 $parse-var-with-type:end:
14715     # . reclaim locals
14716     81 0/subop/add %esp 8/imm32
14717     # . restore registers
14718     5f/pop-to-edi
14719     5e/pop-to-esi
14720     5b/pop-to-ebx
14721     5a/pop-to-edx
14722     59/pop-to-ecx
14723     58/pop-to-eax
14724     # . epilogue
14725     89/<- %esp 5/r32/ebp
14726     5d/pop-to-ebp
14727     c3/return
14728 
14729 $parse-var-with-type:abort:
14730     # error("var should have form 'name: type' in '" line "'\n")
14731     (write-buffered *(ebp+0x14) "var should have form 'name: type' in '")
14732     (flush *(ebp+0x14))
14733     (rewind-stream *(ebp+0xc))
14734     (write-stream-data *(ebp+0x14) *(ebp+0xc))
14735     (write-buffered *(ebp+0x14) "'\n")
14736     (flush *(ebp+0x14))
14737     (stop *(ebp+0x18) 1)
14738     # never gets here
14739 
14740 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
14741     # pseudocode:
14742     #   var s: slice = next-mu-token(in)
14743     #   assert s != ""
14744     #   assert s != "->"
14745     #   assert s != "{"
14746     #   assert s != "}"
14747     #   if s == ")"
14748     #     return
14749     #   out = allocate(Type-tree)
14750     #   if s != "("
14751     #     HACK: if s is an int, parse and return it
14752     #     out->is-atom? = true
14753     #     if (s[0] == "_")
14754     #       out->value = type-parameter
14755     #       out->parameter-name = slice-to-string(ad, s)
14756     #     else
14757     #       out->value = pos-or-insert-slice(Type-id, s)
14758     #     return
14759     #   out->left = parse-type(ad, in)
14760     #   out->right = parse-type-tree(ad, in)
14761     #
14762     # . prologue
14763     55/push-ebp
14764     89/<- %ebp 4/r32/esp
14765     # . save registers
14766     50/push-eax
14767     51/push-ecx
14768     52/push-edx
14769     # clear out
14770     (zero-out *(ebp+0x10) *Handle-size)
14771     # var s/ecx: slice
14772     68/push 0/imm32
14773     68/push 0/imm32
14774     89/<- %ecx 4/r32/esp
14775     # s = next-mu-token(in)
14776     (next-mu-token *(ebp+0xc) %ecx)
14777 #?     (write-buffered Stderr "tok: ")
14778 #?     (write-slice-buffered Stderr %ecx)
14779 #?     (write-buffered Stderr "$\n")
14780 #?     (flush Stderr)
14781     # assert s != ""
14782     (slice-equal? %ecx "")  # => eax
14783     3d/compare-eax-and 0/imm32/false
14784     0f 85/jump-if-!= $parse-type:abort/disp32
14785     # assert s != "{"
14786     (slice-equal? %ecx "{")  # => eax
14787     3d/compare-eax-and 0/imm32/false
14788     0f 85/jump-if-!= $parse-type:abort/disp32
14789     # assert s != "}"
14790     (slice-equal? %ecx "}")  # => eax
14791     3d/compare-eax-and 0/imm32/false
14792     0f 85/jump-if-!= $parse-type:abort/disp32
14793     # assert s != "->"
14794     (slice-equal? %ecx "->")  # => eax
14795     3d/compare-eax-and 0/imm32/false
14796     0f 85/jump-if-!= $parse-type:abort/disp32
14797     # if (s == ")") return
14798     (slice-equal? %ecx ")")  # => eax
14799     3d/compare-eax-and 0/imm32/false
14800     0f 85/jump-if-!= $parse-type:end/disp32
14801     # out = new tree
14802     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
14803     # var out-addr/edx: (addr type-tree) = lookup(*out)
14804     8b/-> *(ebp+0x10) 2/r32/edx
14805     (lookup *edx *(edx+4))  # => eax
14806     89/<- %edx 0/r32/eax
14807     {
14808       # if (s != "(") break
14809       (slice-equal? %ecx "(")  # => eax
14810       3d/compare-eax-and 0/imm32/false
14811       0f 85/jump-if-!= break/disp32
14812       # if s is a number, store it in the type's size field
14813       {
14814 $parse-type:check-for-int:
14815         # var tmp/eax: byte = *s->slice
14816         8b/-> *ecx 0/r32/eax
14817         8a/copy-byte *eax 0/r32/AL
14818         81 4/subop/and %eax 0xff/imm32
14819         # TODO: raise an error on `var x: (array int a)`
14820         (is-decimal-digit? %eax)  # => eax
14821         3d/compare-eax-and 0/imm32/false
14822         74/jump-if-= break/disp8
14823         #
14824         (is-hex-int? %ecx)  # => eax
14825         3d/compare-eax-and 0/imm32/false
14826         74/jump-if-= break/disp8
14827 $parse-type:int:
14828         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
14829         (parse-hex-int-from-slice %ecx)  # => eax
14830         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
14831         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
14832         e9/jump $parse-type:end/disp32
14833       }
14834 $parse-type:atom:
14835       # out->is-atom? = true
14836       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
14837       {
14838 $parse-type:check-for-type-parameter:
14839         # var tmp/eax: byte = *s->slice
14840         8b/-> *ecx 0/r32/eax
14841         8a/copy-byte *eax 0/r32/AL
14842         81 4/subop/and %eax 0xff/imm32
14843         # if (tmp != '_') break
14844         3d/compare-eax-and 0x5f/imm32/_
14845         75/jump-if-!= break/disp8
14846 $parse-type:type-parameter:
14847         # out->value = type-parameter
14848         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
14849         # out->parameter-name = slice-to-string(ad, s)
14850         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
14851         (slice-to-string *(ebp+8) %ecx %eax)
14852         e9/jump $parse-type:end/disp32
14853       }
14854 $parse-type:non-type-parameter:
14855       # out->value = pos-or-insert-slice(Type-id, s)
14856       (pos-or-insert-slice Type-id %ecx)  # => eax
14857       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
14858       e9/jump $parse-type:end/disp32
14859     }
14860 $parse-type:non-atom:
14861     # otherwise s == "("
14862     # out->left = parse-type(ad, in)
14863     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
14864     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14865     # out->right = parse-type-tree(ad, in)
14866     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
14867     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14868 $parse-type:end:
14869     # . reclaim locals
14870     81 0/subop/add %esp 8/imm32
14871     # . restore registers
14872     5a/pop-to-edx
14873     59/pop-to-ecx
14874     58/pop-to-eax
14875     # . epilogue
14876     89/<- %esp 5/r32/ebp
14877     5d/pop-to-ebp
14878     c3/return
14879 
14880 $parse-type:abort:
14881     # error("unexpected token when parsing type: '" s "'\n")
14882     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
14883     (write-slice-buffered *(ebp+0x14) %ecx)
14884     (write-buffered *(ebp+0x14) "'\n")
14885     (flush *(ebp+0x14))
14886     (stop *(ebp+0x18) 1)
14887     # never gets here
14888 
14889 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
14890     # pseudocode:
14891     #   var tmp: (handle type-tree) = parse-type(ad, in)
14892     #   if tmp == 0
14893     #     return 0
14894     #   out = allocate(Type-tree)
14895     #   out->left = tmp
14896     #   out->right = parse-type-tree(ad, in)
14897     #
14898     # . prologue
14899     55/push-ebp
14900     89/<- %ebp 4/r32/esp
14901     # . save registers
14902     50/push-eax
14903     51/push-ecx
14904     52/push-edx
14905     #
14906     (zero-out *(ebp+0x10) *Handle-size)
14907     # var tmp/ecx: (handle type-tree)
14908     68/push 0/imm32
14909     68/push 0/imm32
14910     89/<- %ecx 4/r32/esp
14911     # tmp = parse-type(ad, in)
14912     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
14913     # if (tmp == 0) return
14914     81 7/subop/compare *ecx 0/imm32
14915     74/jump-if-= $parse-type-tree:end/disp8
14916     # out = new tree
14917     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
14918     # var out-addr/edx: (addr tree) = lookup(*out)
14919     8b/-> *(ebp+0x10) 2/r32/edx
14920     (lookup *edx *(edx+4))  # => eax
14921     89/<- %edx 0/r32/eax
14922     # out->left = tmp
14923     8b/-> *ecx 0/r32/eax
14924     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
14925     8b/-> *(ecx+4) 0/r32/eax
14926     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
14927     # out->right = parse-type-tree(ad, in)
14928     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
14929     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
14930 $parse-type-tree:end:
14931     # . reclaim locals
14932     81 0/subop/add %esp 8/imm32
14933     # . restore registers
14934     5a/pop-to-edx
14935     59/pop-to-ecx
14936     58/pop-to-eax
14937     # . epilogue
14938     89/<- %esp 5/r32/ebp
14939     5d/pop-to-ebp
14940     c3/return
14941 
14942 next-mu-token:  # in: (addr stream byte), out: (addr slice)
14943     # pseudocode:
14944     # start:
14945     #   skip-chars-matching-whitespace(in)
14946     #   if in->read >= in->write              # end of in
14947     #     out = {0, 0}
14948     #     return
14949     #   out->start = &in->data[in->read]
14950     #   var curr-byte/eax: byte = in->data[in->read]
14951     #   if curr->byte == ','                  # comment token
14952     #     ++in->read
14953     #     goto start
14954     #   if curr-byte == '#'                   # comment
14955     #     goto done                             # treat as eof
14956     #   if curr-byte == '"'                   # string literal
14957     #     skip-string(in)
14958     #     goto done                           # no metadata
14959     #   if curr-byte == '('
14960     #     ++in->read
14961     #     goto done
14962     #   if curr-byte == ')'
14963     #     ++in->read
14964     #     goto done
14965     #   # read a word
14966     #   while true
14967     #     if in->read >= in->write
14968     #       break
14969     #     curr-byte = in->data[in->read]
14970     #     if curr-byte == ' '
14971     #       break
14972     #     if curr-byte == '\r'
14973     #       break
14974     #     if curr-byte == '\n'
14975     #       break
14976     #     if curr-byte == '('
14977     #       break
14978     #     if curr-byte == ')'
14979     #       break
14980     #     if curr-byte == ','
14981     #       break
14982     #     ++in->read
14983     # done:
14984     #   out->end = &in->data[in->read]
14985     #
14986     # . prologue
14987     55/push-ebp
14988     89/<- %ebp 4/r32/esp
14989     # . save registers
14990     50/push-eax
14991     51/push-ecx
14992     56/push-esi
14993     57/push-edi
14994     # esi = in
14995     8b/-> *(ebp+8) 6/r32/esi
14996     # edi = out
14997     8b/-> *(ebp+0xc) 7/r32/edi
14998 $next-mu-token:start:
14999     (skip-chars-matching-whitespace %esi)
15000 $next-mu-token:check0:
15001     # if (in->read >= in->write) return out = {0, 0}
15002     # . ecx = in->read
15003     8b/-> *(esi+4) 1/r32/ecx
15004     # . if (ecx >= in->write) return out = {0, 0}
15005     3b/compare<- *esi 1/r32/ecx
15006     c7 0/subop/copy *edi 0/imm32
15007     c7 0/subop/copy *(edi+4) 0/imm32
15008     0f 8d/jump-if->= $next-mu-token:end/disp32
15009     # out->start = &in->data[in->read]
15010     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
15011     89/<- *edi 0/r32/eax
15012     # var curr-byte/eax: byte = in->data[in->read]
15013     31/xor-with %eax 0/r32/eax
15014     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
15015     {
15016 $next-mu-token:check-for-comma:
15017       # if (curr-byte != ',') break
15018       3d/compare-eax-and 0x2c/imm32/comma
15019       75/jump-if-!= break/disp8
15020       # ++in->read
15021       ff 0/subop/increment *(esi+4)
15022       # restart
15023       e9/jump $next-mu-token:start/disp32
15024     }
15025     {
15026 $next-mu-token:check-for-comment:
15027       # if (curr-byte != '#') break
15028       3d/compare-eax-and 0x23/imm32/pound
15029       75/jump-if-!= break/disp8
15030       # return eof
15031       e9/jump $next-mu-token:done/disp32
15032     }
15033     {
15034 $next-mu-token:check-for-string-literal:
15035       # if (curr-byte != '"') break
15036       3d/compare-eax-and 0x22/imm32/dquote
15037       75/jump-if-!= break/disp8
15038       (skip-string %esi)
15039       # return
15040       e9/jump $next-mu-token:done/disp32
15041     }
15042     {
15043 $next-mu-token:check-for-open-paren:
15044       # if (curr-byte != '(') break
15045       3d/compare-eax-and 0x28/imm32/open-paren
15046       75/jump-if-!= break/disp8
15047       # ++in->read
15048       ff 0/subop/increment *(esi+4)
15049       # return
15050       e9/jump $next-mu-token:done/disp32
15051     }
15052     {
15053 $next-mu-token:check-for-close-paren:
15054       # if (curr-byte != ')') break
15055       3d/compare-eax-and 0x29/imm32/close-paren
15056       75/jump-if-!= break/disp8
15057       # ++in->read
15058       ff 0/subop/increment *(esi+4)
15059       # return
15060       e9/jump $next-mu-token:done/disp32
15061     }
15062     {
15063 $next-mu-token:regular-word-without-metadata:
15064       # if (in->read >= in->write) break
15065       # . ecx = in->read
15066       8b/-> *(esi+4) 1/r32/ecx
15067       # . if (ecx >= in->write) break
15068       3b/compare<- *esi 1/r32/ecx
15069       7d/jump-if->= break/disp8
15070       # var c/eax: byte = in->data[in->read]
15071       31/xor-with %eax 0/r32/eax
15072       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
15073       # if (c == ' ') break
15074       3d/compare-eax-and 0x20/imm32/space
15075       74/jump-if-= break/disp8
15076       # if (c == '\r') break
15077       3d/compare-eax-and 0xd/imm32/carriage-return
15078       74/jump-if-= break/disp8
15079       # if (c == '\n') break
15080       3d/compare-eax-and 0xa/imm32/newline
15081       74/jump-if-= break/disp8
15082       # if (c == '(') break
15083       3d/compare-eax-and 0x28/imm32/open-paren
15084       0f 84/jump-if-= break/disp32
15085       # if (c == ')') break
15086       3d/compare-eax-and 0x29/imm32/close-paren
15087       0f 84/jump-if-= break/disp32
15088       # if (c == ',') break
15089       3d/compare-eax-and 0x2c/imm32/comma
15090       0f 84/jump-if-= break/disp32
15091       # ++in->read
15092       ff 0/subop/increment *(esi+4)
15093       #
15094       e9/jump loop/disp32
15095     }
15096 $next-mu-token:done:
15097     # out->end = &in->data[in->read]
15098     8b/-> *(esi+4) 1/r32/ecx
15099     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
15100     89/<- *(edi+4) 0/r32/eax
15101 $next-mu-token:end:
15102     # . restore registers
15103     5f/pop-to-edi
15104     5e/pop-to-esi
15105     59/pop-to-ecx
15106     58/pop-to-eax
15107     # . epilogue
15108     89/<- %esp 5/r32/ebp
15109     5d/pop-to-ebp
15110     c3/return
15111 
15112 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
15113     # . prologue
15114     55/push-ebp
15115     89/<- %ebp 4/r32/esp
15116     # if (pos-slice(arr, s) != -1) return it
15117     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
15118     3d/compare-eax-and -1/imm32
15119     75/jump-if-!= $pos-or-insert-slice:end/disp8
15120 $pos-or-insert-slice:insert:
15121     # var s2/eax: (handle array byte)
15122     68/push 0/imm32
15123     68/push 0/imm32
15124     89/<- %eax 4/r32/esp
15125     (slice-to-string Heap *(ebp+0xc) %eax)
15126     # throw away alloc-id
15127     (lookup *eax *(eax+4))  # => eax
15128     (write-int *(ebp+8) %eax)
15129     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
15130 $pos-or-insert-slice:end:
15131     # . reclaim locals
15132     81 0/subop/add %esp 8/imm32
15133     # . epilogue
15134     89/<- %esp 5/r32/ebp
15135     5d/pop-to-ebp
15136     c3/return
15137 
15138 # return the index in an array of strings matching 's', -1 if not found
15139 # index is denominated in elements, not bytes
15140 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
15141     # . prologue
15142     55/push-ebp
15143     89/<- %ebp 4/r32/esp
15144     # . save registers
15145     51/push-ecx
15146     52/push-edx
15147     53/push-ebx
15148     56/push-esi
15149 #?     (write-buffered Stderr "pos-slice: ")
15150 #?     (write-slice-buffered Stderr *(ebp+0xc))
15151 #?     (write-buffered Stderr "\n")
15152 #?     (flush Stderr)
15153     # esi = arr
15154     8b/-> *(ebp+8) 6/r32/esi
15155     # var index/ecx: int = 0
15156     b9/copy-to-ecx 0/imm32
15157     # var curr/edx: (addr (addr array byte)) = arr->data
15158     8d/copy-address *(esi+0xc) 2/r32/edx
15159     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
15160     8b/-> *esi 3/r32/ebx
15161     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
15162     {
15163 #?       (write-buffered Stderr "  ")
15164 #?       (write-int32-hex-buffered Stderr %ecx)
15165 #?       (write-buffered Stderr "\n")
15166 #?       (flush Stderr)
15167       # if (curr >= max) return -1
15168       39/compare %edx 3/r32/ebx
15169       b8/copy-to-eax -1/imm32
15170       73/jump-if-addr>= $pos-slice:end/disp8
15171       # if (slice-equal?(s, *curr)) break
15172       (slice-equal? *(ebp+0xc) *edx)  # => eax
15173       3d/compare-eax-and 0/imm32/false
15174       75/jump-if-!= break/disp8
15175       # ++index
15176       41/increment-ecx
15177       # curr += 4
15178       81 0/subop/add %edx 4/imm32
15179       #
15180       eb/jump loop/disp8
15181     }
15182     # return index
15183     89/<- %eax 1/r32/ecx
15184 $pos-slice:end:
15185 #?     (write-buffered Stderr "=> ")
15186 #?     (write-int32-hex-buffered Stderr %eax)
15187 #?     (write-buffered Stderr "\n")
15188     # . restore registers
15189     5e/pop-to-esi
15190     5b/pop-to-ebx
15191     5a/pop-to-edx
15192     59/pop-to-ecx
15193     # . epilogue
15194     89/<- %esp 5/r32/ebp
15195     5d/pop-to-ebp
15196     c3/return
15197 
15198 test-parse-var-with-type:
15199     # . prologue
15200     55/push-ebp
15201     89/<- %ebp 4/r32/esp
15202     # setup
15203     8b/-> *Primitive-type-ids 0/r32/eax
15204     89/<- *Type-id 0/r32/eax  # stream-write
15205     # (eax..ecx) = "x:"
15206     b8/copy-to-eax "x:"/imm32
15207     8b/-> *eax 1/r32/ecx
15208     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15209     05/add-to-eax 4/imm32
15210     # var slice/ecx: slice = {eax, ecx}
15211     51/push-ecx
15212     50/push-eax
15213     89/<- %ecx 4/r32/esp
15214     # _test-input-stream contains "int"
15215     (clear-stream _test-input-stream)
15216     (write _test-input-stream "int")
15217     # var v/edx: (handle var)
15218     68/push 0/imm32
15219     68/push 0/imm32
15220     89/<- %edx 4/r32/esp
15221     #
15222     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
15223     # var v-addr/edx: (addr var) = lookup(v)
15224     (lookup *edx *(edx+4))  # => eax
15225     89/<- %edx 0/r32/eax
15226     # check v-addr->name
15227     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15228     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
15229     # check v-addr->type
15230     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15231     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
15232     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
15233     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
15234     # . epilogue
15235     89/<- %esp 5/r32/ebp
15236     5d/pop-to-ebp
15237     c3/return
15238 
15239 test-parse-var-with-type-and-register:
15240     # . prologue
15241     55/push-ebp
15242     89/<- %ebp 4/r32/esp
15243     # setup
15244     8b/-> *Primitive-type-ids 0/r32/eax
15245     89/<- *Type-id 0/r32/eax  # stream-write
15246     # (eax..ecx) = "x/eax:"
15247     b8/copy-to-eax "x/eax:"/imm32
15248     8b/-> *eax 1/r32/ecx
15249     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15250     05/add-to-eax 4/imm32
15251     # var slice/ecx: slice = {eax, ecx}
15252     51/push-ecx
15253     50/push-eax
15254     89/<- %ecx 4/r32/esp
15255     # _test-input-stream contains "int"
15256     (clear-stream _test-input-stream)
15257     (write _test-input-stream "int")
15258     # var v/edx: (handle var)
15259     68/push 0/imm32
15260     68/push 0/imm32
15261     89/<- %edx 4/r32/esp
15262     #
15263     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
15264     # var v-addr/edx: (addr var) = lookup(v)
15265     (lookup *edx *(edx+4))  # => eax
15266     89/<- %edx 0/r32/eax
15267     # check v-addr->name
15268     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15269     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
15270     # check v-addr->register
15271     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
15272     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
15273     # check v-addr->type
15274     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15275     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
15276     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
15277     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
15278     # . epilogue
15279     89/<- %esp 5/r32/ebp
15280     5d/pop-to-ebp
15281     c3/return
15282 
15283 test-parse-var-with-trailing-characters:
15284     # . prologue
15285     55/push-ebp
15286     89/<- %ebp 4/r32/esp
15287     # setup
15288     8b/-> *Primitive-type-ids 0/r32/eax
15289     89/<- *Type-id 0/r32/eax  # stream-write
15290     # (eax..ecx) = "x:"
15291     b8/copy-to-eax "x:"/imm32
15292     8b/-> *eax 1/r32/ecx
15293     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15294     05/add-to-eax 4/imm32
15295     # var slice/ecx: slice = {eax, ecx}
15296     51/push-ecx
15297     50/push-eax
15298     89/<- %ecx 4/r32/esp
15299     # _test-input-stream contains "int,"
15300     (clear-stream _test-input-stream)
15301     (write _test-input-stream "int,")
15302     # var v/edx: (handle var)
15303     68/push 0/imm32
15304     68/push 0/imm32
15305     89/<- %edx 4/r32/esp
15306     #
15307     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
15308     # var v-addr/edx: (addr var) = lookup(v)
15309     (lookup *edx *(edx+4))  # => eax
15310     89/<- %edx 0/r32/eax
15311     # check v-addr->name
15312     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15313     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
15314     # check v-addr->register
15315     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
15316     # check v-addr->type
15317     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15318     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
15319     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
15320     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
15321     # . epilogue
15322     89/<- %esp 5/r32/ebp
15323     5d/pop-to-ebp
15324     c3/return
15325 
15326 test-parse-var-with-register-and-trailing-characters:
15327     # . prologue
15328     55/push-ebp
15329     89/<- %ebp 4/r32/esp
15330     # setup
15331     8b/-> *Primitive-type-ids 0/r32/eax
15332     89/<- *Type-id 0/r32/eax  # stream-write
15333     # (eax..ecx) = "x/eax:"
15334     b8/copy-to-eax "x/eax:"/imm32
15335     8b/-> *eax 1/r32/ecx
15336     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15337     05/add-to-eax 4/imm32
15338     # var slice/ecx: slice = {eax, ecx}
15339     51/push-ecx
15340     50/push-eax
15341     89/<- %ecx 4/r32/esp
15342     # _test-input-stream contains "int,"
15343     (clear-stream _test-input-stream)
15344     (write _test-input-stream "int,")
15345     # var v/edx: (handle var)
15346     68/push 0/imm32
15347     68/push 0/imm32
15348     89/<- %edx 4/r32/esp
15349     #
15350     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
15351     # var v-addr/edx: (addr var) = lookup(v)
15352     (lookup *edx *(edx+4))  # => eax
15353     89/<- %edx 0/r32/eax
15354     # check v-addr->name
15355     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15356     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
15357     # check v-addr->register
15358     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
15359     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
15360     # check v-addr->type
15361     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15362     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
15363     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
15364     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
15365     # . epilogue
15366     89/<- %esp 5/r32/ebp
15367     5d/pop-to-ebp
15368     c3/return
15369 
15370 test-parse-var-with-compound-type:
15371     # . prologue
15372     55/push-ebp
15373     89/<- %ebp 4/r32/esp
15374     # setup
15375     8b/-> *Primitive-type-ids 0/r32/eax
15376     89/<- *Type-id 0/r32/eax  # stream-write
15377     # (eax..ecx) = "x:"
15378     b8/copy-to-eax "x:"/imm32
15379     8b/-> *eax 1/r32/ecx
15380     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15381     05/add-to-eax 4/imm32
15382     # var slice/ecx: slice = {eax, ecx}
15383     51/push-ecx
15384     50/push-eax
15385     89/<- %ecx 4/r32/esp
15386     # _test-input-stream contains "(addr int)"
15387     (clear-stream _test-input-stream)
15388     (write _test-input-stream "(addr int)")
15389     # var v/edx: (handle var)
15390     68/push 0/imm32
15391     68/push 0/imm32
15392     89/<- %edx 4/r32/esp
15393     #
15394     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
15395     # var v-addr/edx: (addr var) = lookup(v)
15396     (lookup *edx *(edx+4))  # => eax
15397     89/<- %edx 0/r32/eax
15398     # check v-addr->name
15399     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15400     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
15401     # check v-addr->register
15402     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
15403     # - check v-addr->type
15404     # var type/edx: (addr type-tree) = var->type
15405     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15406     89/<- %edx 0/r32/eax
15407     # type is a non-atom
15408     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
15409     # type->left == atom(addr)
15410     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
15411     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
15412     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
15413     # type->right->left == atom(int)
15414     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
15415     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15416     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
15417     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
15418     # type->right->right == null
15419     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
15420     # . epilogue
15421     89/<- %esp 5/r32/ebp
15422     5d/pop-to-ebp
15423     c3/return
15424 
15425 # identifier starts with a letter or '$' or '_'
15426 # no constraints at the moment on later letters
15427 # all we really want to do so far is exclude '{', '}' and '->'
15428 is-identifier?:  # in: (addr slice) -> result/eax: boolean
15429     # . prologue
15430     55/push-ebp
15431     89/<- %ebp 4/r32/esp
15432     # if (slice-empty?(in)) return false
15433     (slice-empty? *(ebp+8))  # => eax
15434     3d/compare-eax-and 0/imm32/false
15435     75/jump-if-!= $is-identifier?:false/disp8
15436     # var c/eax: byte = *in->start
15437     8b/-> *(ebp+8) 0/r32/eax
15438     8b/-> *eax 0/r32/eax
15439     8a/copy-byte *eax 0/r32/AL
15440     81 4/subop/and %eax 0xff/imm32
15441     # if (c == '$') return true
15442     3d/compare-eax-and 0x24/imm32/$
15443     74/jump-if-= $is-identifier?:true/disp8
15444     # if (c == '_') return true
15445     3d/compare-eax-and 0x5f/imm32/_
15446     74/jump-if-= $is-identifier?:true/disp8
15447     # drop case
15448     25/and-eax-with 0x5f/imm32
15449     # if (c < 'A') return false
15450     3d/compare-eax-and 0x41/imm32/A
15451     7c/jump-if-< $is-identifier?:false/disp8
15452     # if (c > 'Z') return false
15453     3d/compare-eax-and 0x5a/imm32/Z
15454     7f/jump-if-> $is-identifier?:false/disp8
15455     # otherwise return true
15456 $is-identifier?:true:
15457     b8/copy-to-eax 1/imm32/true
15458     eb/jump $is-identifier?:end/disp8
15459 $is-identifier?:false:
15460     b8/copy-to-eax 0/imm32/false
15461 $is-identifier?:end:
15462     # . epilogue
15463     89/<- %esp 5/r32/ebp
15464     5d/pop-to-ebp
15465     c3/return
15466 
15467 test-is-identifier-dollar:
15468     # . prologue
15469     55/push-ebp
15470     89/<- %ebp 4/r32/esp
15471     # (eax..ecx) = "$a"
15472     b8/copy-to-eax "$a"/imm32
15473     8b/-> *eax 1/r32/ecx
15474     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15475     05/add-to-eax 4/imm32
15476     # var slice/ecx: slice = {eax, ecx}
15477     51/push-ecx
15478     50/push-eax
15479     89/<- %ecx 4/r32/esp
15480     #
15481     (is-identifier? %ecx)
15482     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
15483     # . epilogue
15484     89/<- %esp 5/r32/ebp
15485     5d/pop-to-ebp
15486     c3/return
15487 
15488 test-is-identifier-underscore:
15489     # . prologue
15490     55/push-ebp
15491     89/<- %ebp 4/r32/esp
15492     # (eax..ecx) = "_a"
15493     b8/copy-to-eax "_a"/imm32
15494     8b/-> *eax 1/r32/ecx
15495     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15496     05/add-to-eax 4/imm32
15497     # var slice/ecx: slice = {eax, ecx}
15498     51/push-ecx
15499     50/push-eax
15500     89/<- %ecx 4/r32/esp
15501     #
15502     (is-identifier? %ecx)
15503     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
15504     # . epilogue
15505     89/<- %esp 5/r32/ebp
15506     5d/pop-to-ebp
15507     c3/return
15508 
15509 test-is-identifier-a:
15510     # . prologue
15511     55/push-ebp
15512     89/<- %ebp 4/r32/esp
15513     # (eax..ecx) = "a$"
15514     b8/copy-to-eax "a$"/imm32
15515     8b/-> *eax 1/r32/ecx
15516     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15517     05/add-to-eax 4/imm32
15518     # var slice/ecx: slice = {eax, ecx}
15519     51/push-ecx
15520     50/push-eax
15521     89/<- %ecx 4/r32/esp
15522     #
15523     (is-identifier? %ecx)
15524     (check-ints-equal %eax 1 "F - test-is-identifier-a")
15525     # . epilogue
15526     89/<- %esp 5/r32/ebp
15527     5d/pop-to-ebp
15528     c3/return
15529 
15530 test-is-identifier-z:
15531     # . prologue
15532     55/push-ebp
15533     89/<- %ebp 4/r32/esp
15534     # (eax..ecx) = "z$"
15535     b8/copy-to-eax "z$"/imm32
15536     8b/-> *eax 1/r32/ecx
15537     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15538     05/add-to-eax 4/imm32
15539     # var slice/ecx: slice = {eax, ecx}
15540     51/push-ecx
15541     50/push-eax
15542     89/<- %ecx 4/r32/esp
15543     #
15544     (is-identifier? %ecx)
15545     (check-ints-equal %eax 1 "F - test-is-identifier-z")
15546     # . epilogue
15547     89/<- %esp 5/r32/ebp
15548     5d/pop-to-ebp
15549     c3/return
15550 
15551 test-is-identifier-A:
15552     # . prologue
15553     55/push-ebp
15554     89/<- %ebp 4/r32/esp
15555     # (eax..ecx) = "A$"
15556     b8/copy-to-eax "A$"/imm32
15557     8b/-> *eax 1/r32/ecx
15558     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15559     05/add-to-eax 4/imm32
15560     # var slice/ecx: slice = {eax, ecx}
15561     51/push-ecx
15562     50/push-eax
15563     89/<- %ecx 4/r32/esp
15564     #
15565     (is-identifier? %ecx)
15566     (check-ints-equal %eax 1 "F - test-is-identifier-A")
15567     # . epilogue
15568     89/<- %esp 5/r32/ebp
15569     5d/pop-to-ebp
15570     c3/return
15571 
15572 test-is-identifier-Z:
15573     # . prologue
15574     55/push-ebp
15575     89/<- %ebp 4/r32/esp
15576     # (eax..ecx) = "Z$"
15577     b8/copy-to-eax "Z$"/imm32
15578     8b/-> *eax 1/r32/ecx
15579     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15580     05/add-to-eax 4/imm32
15581     # var slice/ecx: slice = {eax, ecx}
15582     51/push-ecx
15583     50/push-eax
15584     89/<- %ecx 4/r32/esp
15585     #
15586     (is-identifier? %ecx)
15587     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
15588     # . epilogue
15589     89/<- %esp 5/r32/ebp
15590     5d/pop-to-ebp
15591     c3/return
15592 
15593 test-is-identifier-at:
15594     # character before 'A' is invalid
15595     # . prologue
15596     55/push-ebp
15597     89/<- %ebp 4/r32/esp
15598     # (eax..ecx) = "@a"
15599     b8/copy-to-eax "@a"/imm32
15600     8b/-> *eax 1/r32/ecx
15601     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15602     05/add-to-eax 4/imm32
15603     # var slice/ecx: slice = {eax, ecx}
15604     51/push-ecx
15605     50/push-eax
15606     89/<- %ecx 4/r32/esp
15607     #
15608     (is-identifier? %ecx)
15609     (check-ints-equal %eax 0 "F - test-is-identifier-@")
15610     # . epilogue
15611     89/<- %esp 5/r32/ebp
15612     5d/pop-to-ebp
15613     c3/return
15614 
15615 test-is-identifier-square-bracket:
15616     # character after 'Z' is invalid
15617     # . prologue
15618     55/push-ebp
15619     89/<- %ebp 4/r32/esp
15620     # (eax..ecx) = "[a"
15621     b8/copy-to-eax "[a"/imm32
15622     8b/-> *eax 1/r32/ecx
15623     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15624     05/add-to-eax 4/imm32
15625     # var slice/ecx: slice = {eax, ecx}
15626     51/push-ecx
15627     50/push-eax
15628     89/<- %ecx 4/r32/esp
15629     #
15630     (is-identifier? %ecx)
15631     (check-ints-equal %eax 0 "F - test-is-identifier-@")
15632     # . epilogue
15633     89/<- %esp 5/r32/ebp
15634     5d/pop-to-ebp
15635     c3/return
15636 
15637 test-is-identifier-backtick:
15638     # character before 'a' is invalid
15639     # . prologue
15640     55/push-ebp
15641     89/<- %ebp 4/r32/esp
15642     # (eax..ecx) = "`a"
15643     b8/copy-to-eax "`a"/imm32
15644     8b/-> *eax 1/r32/ecx
15645     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15646     05/add-to-eax 4/imm32
15647     # var slice/ecx: slice = {eax, ecx}
15648     51/push-ecx
15649     50/push-eax
15650     89/<- %ecx 4/r32/esp
15651     #
15652     (is-identifier? %ecx)
15653     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
15654     # . epilogue
15655     89/<- %esp 5/r32/ebp
15656     5d/pop-to-ebp
15657     c3/return
15658 
15659 test-is-identifier-curly-brace-open:
15660     # character after 'z' is invalid; also used for blocks
15661     # . prologue
15662     55/push-ebp
15663     89/<- %ebp 4/r32/esp
15664     # (eax..ecx) = "{a"
15665     b8/copy-to-eax "{a"/imm32
15666     8b/-> *eax 1/r32/ecx
15667     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15668     05/add-to-eax 4/imm32
15669     # var slice/ecx: slice = {eax, ecx}
15670     51/push-ecx
15671     50/push-eax
15672     89/<- %ecx 4/r32/esp
15673     #
15674     (is-identifier? %ecx)
15675     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
15676     # . epilogue
15677     89/<- %esp 5/r32/ebp
15678     5d/pop-to-ebp
15679     c3/return
15680 
15681 test-is-identifier-curly-brace-close:
15682     # . prologue
15683     55/push-ebp
15684     89/<- %ebp 4/r32/esp
15685     # (eax..ecx) = "}a"
15686     b8/copy-to-eax "}a"/imm32
15687     8b/-> *eax 1/r32/ecx
15688     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15689     05/add-to-eax 4/imm32
15690     # var slice/ecx: slice = {eax, ecx}
15691     51/push-ecx
15692     50/push-eax
15693     89/<- %ecx 4/r32/esp
15694     #
15695     (is-identifier? %ecx)
15696     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
15697     # . epilogue
15698     89/<- %esp 5/r32/ebp
15699     5d/pop-to-ebp
15700     c3/return
15701 
15702 test-is-identifier-hyphen:
15703     # disallow leading '-' since '->' has special meaning
15704     # . prologue
15705     55/push-ebp
15706     89/<- %ebp 4/r32/esp
15707     # (eax..ecx) = "-a"
15708     b8/copy-to-eax "-a"/imm32
15709     8b/-> *eax 1/r32/ecx
15710     8d/copy-address *(eax+ecx+4) 1/r32/ecx
15711     05/add-to-eax 4/imm32
15712     # var slice/ecx: slice = {eax, ecx}
15713     51/push-ecx
15714     50/push-eax
15715     89/<- %ecx 4/r32/esp
15716     #
15717     (is-identifier? %ecx)
15718     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
15719     # . epilogue
15720     89/<- %esp 5/r32/ebp
15721     5d/pop-to-ebp
15722     c3/return
15723 
15724 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
15725     # . prologue
15726     55/push-ebp
15727     89/<- %ebp 4/r32/esp
15728     # . save registers
15729     50/push-eax
15730     56/push-esi
15731     57/push-edi
15732     # esi = in
15733     8b/-> *(ebp+8) 6/r32/esi
15734     # edi = out
15735     8b/-> *(ebp+0xc) 7/r32/edi
15736     # initialize some global state
15737     c7 0/subop/copy *Curr-block-depth 1/imm32
15738     # parse-mu-block(in, vars, out, out->body)
15739     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
15740     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
15741 $populate-mu-function-body:end:
15742     # . restore registers
15743     5f/pop-to-edi
15744     5e/pop-to-esi
15745     58/pop-to-eax
15746     # . epilogue
15747     89/<- %esp 5/r32/ebp
15748     5d/pop-to-ebp
15749     c3/return
15750 
15751 # parses a block, assuming that the leading '{' has already been read by the caller
15752 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)
15753     # pseudocode:
15754     #   var line: (stream byte 512)
15755     #   var word-slice: slice
15756     #   allocate(Heap, Stmt-size, out)
15757     #   var out-addr: (addr block) = lookup(*out)
15758     #   out-addr->tag = 0/block
15759     #   out-addr->var = some unique name
15760     #   push(vars, {out-addr->var, false})
15761     #   while true                                  # line loop
15762     #     clear-stream(line)
15763     #     read-line-buffered(in, line)
15764     #     if (line->write == 0) break               # end of file
15765     #     word-slice = next-mu-token(line)
15766     #     if slice-empty?(word-slice)               # end of line
15767     #       continue
15768     #     else if slice-starts-with?(word-slice, "#")
15769     #       continue
15770     #     else if slice-equal?(word-slice, "{")
15771     #       assert(no-tokens-in(line))
15772     #       block = parse-mu-block(in, vars, fn)
15773     #       append-to-block(out-addr, block)
15774     #     else if slice-equal?(word-slice, "}")
15775     #       break
15776     #     else if slice-ends-with?(word-slice, ":")
15777     #       # TODO: error-check the rest of 'line'
15778     #       --word-slice->end to skip ':'
15779     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
15780     #       append-to-block(out-addr, named-block)
15781     #     else if slice-equal?(word-slice, "var")
15782     #       var-def = parse-mu-var-def(line, vars, fn)
15783     #       append-to-block(out-addr, var-def)
15784     #     else
15785     #       stmt = parse-mu-stmt(line, vars, fn)
15786     #       append-to-block(out-addr, stmt)
15787     #   pop(vars)
15788     #
15789     # . prologue
15790     55/push-ebp
15791     89/<- %ebp 4/r32/esp
15792     # . save registers
15793     50/push-eax
15794     51/push-ecx
15795     52/push-edx
15796     53/push-ebx
15797     57/push-edi
15798     # var line/ecx: (stream byte 512)
15799     81 5/subop/subtract %esp 0x200/imm32
15800     68/push 0x200/imm32/size
15801     68/push 0/imm32/read
15802     68/push 0/imm32/write
15803     89/<- %ecx 4/r32/esp
15804     # var word-slice/edx: slice
15805     68/push 0/imm32/end
15806     68/push 0/imm32/start
15807     89/<- %edx 4/r32/esp
15808     # allocate into out
15809     (allocate Heap *Stmt-size *(ebp+0x14))
15810     # var out-addr/edi: (addr block) = lookup(*out)
15811     8b/-> *(ebp+0x14) 7/r32/edi
15812     (lookup *edi *(edi+4))  # => eax
15813     89/<- %edi 0/r32/eax
15814     # out-addr->tag is 0 (block) by default
15815     # set out-addr->var
15816     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
15817     (new-block-name *(ebp+0x10) %eax)
15818     # push(vars, out-addr->var)
15819     (push *(ebp+0xc) *(edi+0xc))  # Block-var
15820     (push *(ebp+0xc) *(edi+0x10))  # Block-var
15821     (push *(ebp+0xc) 0)  # false
15822     # increment *Curr-block-depth
15823     ff 0/subop/increment *Curr-block-depth
15824     {
15825 $parse-mu-block:line-loop:
15826       # line = read-line-buffered(in)
15827       (clear-stream %ecx)
15828       (read-line-buffered *(ebp+8) %ecx)
15829 #?       (write-buffered Stderr "line: ")
15830 #?       (write-stream-data Stderr %ecx)
15831 #? #?       (write-buffered Stderr Newline)  # line has its own newline
15832 #?       (flush Stderr)
15833 #?       (rewind-stream %ecx)
15834       # if (line->write == 0) break
15835       81 7/subop/compare *ecx 0/imm32
15836       0f 84/jump-if-= break/disp32
15837 #?       (write-buffered Stderr "vars:\n")
15838 #?       (dump-vars *(ebp+0xc))
15839       # word-slice = next-mu-token(line)
15840       (next-mu-token %ecx %edx)
15841 #?       (write-buffered Stderr "word: ")
15842 #?       (write-slice-buffered Stderr %edx)
15843 #?       (write-buffered Stderr Newline)
15844 #?       (flush Stderr)
15845       # if slice-empty?(word-slice) continue
15846       (slice-empty? %edx)
15847       3d/compare-eax-and 0/imm32/false
15848       0f 85/jump-if-!= loop/disp32
15849       # if (slice-starts-with?(word-slice, '#') continue
15850       # . eax = *word-slice->start
15851       8b/-> *edx 0/r32/eax
15852       8a/copy-byte *eax 0/r32/AL
15853       81 4/subop/and %eax 0xff/imm32
15854       # . if (eax == '#') continue
15855       3d/compare-eax-and 0x23/imm32/hash
15856       0f 84/jump-if-= loop/disp32
15857       # if slice-equal?(word-slice, "{")
15858       {
15859 $parse-mu-block:check-for-block:
15860         (slice-equal? %edx "{")
15861         3d/compare-eax-and 0/imm32/false
15862         74/jump-if-= break/disp8
15863         (check-no-tokens-left %ecx)
15864         # parse new block and append
15865         # . var tmp/eax: (handle block)
15866         68/push 0/imm32
15867         68/push 0/imm32
15868         89/<- %eax 4/r32/esp
15869         # .
15870         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
15871         (append-to-block Heap %edi  *eax *(eax+4))
15872         # . reclaim tmp
15873         81 0/subop/add %esp 8/imm32
15874         # .
15875         e9/jump $parse-mu-block:line-loop/disp32
15876       }
15877       # if slice-equal?(word-slice, "}") break
15878 $parse-mu-block:check-for-end:
15879       (slice-equal? %edx "}")
15880       3d/compare-eax-and 0/imm32/false
15881       0f 85/jump-if-!= break/disp32
15882       # if slice-ends-with?(word-slice, ":") parse named block and append
15883       {
15884 $parse-mu-block:check-for-named-block:
15885         # . eax = *(word-slice->end-1)
15886         8b/-> *(edx+4) 0/r32/eax
15887         48/decrement-eax
15888         8a/copy-byte *eax 0/r32/AL
15889         81 4/subop/and %eax 0xff/imm32
15890         # . if (eax != ':') break
15891         3d/compare-eax-and 0x3a/imm32/colon
15892         0f 85/jump-if-!= break/disp32
15893         # TODO: error-check the rest of 'line'
15894         #
15895         # skip ':'
15896         ff 1/subop/decrement *(edx+4)  # Slice-end
15897         # var tmp/eax: (handle block)
15898         68/push 0/imm32
15899         68/push 0/imm32
15900         89/<- %eax 4/r32/esp
15901         #
15902         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
15903         (append-to-block Heap %edi  *eax *(eax+4))
15904         # reclaim tmp
15905         81 0/subop/add %esp 8/imm32
15906         #
15907         e9/jump $parse-mu-block:line-loop/disp32
15908       }
15909       # if slice-equal?(word-slice, "var")
15910       {
15911 $parse-mu-block:check-for-var:
15912         (slice-equal? %edx "var")
15913         3d/compare-eax-and 0/imm32/false
15914         74/jump-if-= break/disp8
15915         # var tmp/eax: (handle block)
15916         68/push 0/imm32
15917         68/push 0/imm32
15918         89/<- %eax 4/r32/esp
15919         #
15920         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
15921         (append-to-block Heap %edi  *eax *(eax+4))
15922         # reclaim tmp
15923         81 0/subop/add %esp 8/imm32
15924         #
15925         e9/jump $parse-mu-block:line-loop/disp32
15926       }
15927 $parse-mu-block:regular-stmt:
15928       # otherwise
15929       # var tmp/eax: (handle block)
15930       68/push 0/imm32
15931       68/push 0/imm32
15932       89/<- %eax 4/r32/esp
15933       #
15934       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
15935       (append-to-block Heap %edi  *eax *(eax+4))
15936       # reclaim tmp
15937       81 0/subop/add %esp 8/imm32
15938       #
15939       e9/jump loop/disp32
15940     } # end line loop
15941     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
15942     # decrement *Curr-block-depth
15943     ff 1/subop/decrement *Curr-block-depth
15944     # pop(vars)
15945     (pop *(ebp+0xc))  # => eax
15946     (pop *(ebp+0xc))  # => eax
15947     (pop *(ebp+0xc))  # => eax
15948 $parse-mu-block:end:
15949     # . reclaim locals
15950     81 0/subop/add %esp 0x214/imm32
15951     # . restore registers
15952     5f/pop-to-edi
15953     5b/pop-to-ebx
15954     5a/pop-to-edx
15955     59/pop-to-ecx
15956     58/pop-to-eax
15957     # . epilogue
15958     89/<- %esp 5/r32/ebp
15959     5d/pop-to-ebp
15960     c3/return
15961 
15962 $parse-mu-block:abort:
15963     # error("'{' or '}' should be on its own line, but got '")
15964     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
15965     (rewind-stream %ecx)
15966     (write-stream-data *(ebp+0x18) %ecx)
15967     (write-buffered *(ebp+0x18) "'\n")
15968     (flush *(ebp+0x18))
15969     (stop *(ebp+0x1c) 1)
15970     # never gets here
15971 
15972 new-block-name:  # fn: (addr function), out: (addr handle var)
15973     # . prologue
15974     55/push-ebp
15975     89/<- %ebp 4/r32/esp
15976     # . save registers
15977     50/push-eax
15978     51/push-ecx
15979     52/push-edx
15980     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
15981     8b/-> *(ebp+8) 0/r32/eax
15982     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15983     8b/-> *eax 0/r32/eax  # String-size
15984     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
15985     89/<- %ecx 0/r32/eax
15986     # var name/edx: (stream byte n)
15987     29/subtract-from %esp 1/r32/ecx
15988     ff 6/subop/push %ecx
15989     68/push 0/imm32/read
15990     68/push 0/imm32/write
15991     89/<- %edx 4/r32/esp
15992     (clear-stream %edx)
15993     # eax = fn->name
15994     8b/-> *(ebp+8) 0/r32/eax
15995     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15996     # construct result using Next-block-index (and increment it)
15997     (write %edx "$")
15998     (write %edx %eax)
15999     (write %edx ":")
16000     (write-int32-hex %edx *Next-block-index)
16001     ff 0/subop/increment *Next-block-index
16002     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
16003     # . eax = name->write
16004     8b/-> *edx 0/r32/eax
16005     # . edx = name->data
16006     8d/copy-address *(edx+0xc) 2/r32/edx
16007     # . eax = name->write + name->data
16008     01/add-to %eax 2/r32/edx
16009     # . push {edx, eax}
16010     ff 6/subop/push %eax
16011     ff 6/subop/push %edx
16012     89/<- %eax 4/r32/esp
16013     # out = new literal(s)
16014     (new-literal Heap %eax *(ebp+0xc))
16015 #?     8b/-> *(ebp+0xc) 0/r32/eax
16016 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
16017 #?     (write-int32-hex-buffered Stderr *(eax+8))
16018 #?     (write-buffered Stderr " for var ")
16019 #?     (write-int32-hex-buffered Stderr %eax)
16020 #?     (write-buffered Stderr Newline)
16021 #?     (flush Stderr)
16022 $new-block-name:end:
16023     # . reclaim locals
16024     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
16025     81 0/subop/add %ecx 8/imm32  # slice
16026     01/add-to %esp 1/r32/ecx
16027     # . restore registers
16028     5a/pop-to-edx
16029     59/pop-to-ecx
16030     58/pop-to-eax
16031     # . epilogue
16032     89/<- %esp 5/r32/ebp
16033     5d/pop-to-ebp
16034     c3/return
16035 
16036 check-no-tokens-left:  # line: (addr stream byte)
16037     # . prologue
16038     55/push-ebp
16039     89/<- %ebp 4/r32/esp
16040     # . save registers
16041     50/push-eax
16042     51/push-ecx
16043     # var s/ecx: slice
16044     68/push 0/imm32/end
16045     68/push 0/imm32/start
16046     89/<- %ecx 4/r32/esp
16047     #
16048     (next-mu-token *(ebp+8) %ecx)
16049     # if slice-empty?(s) return
16050     (slice-empty? %ecx)
16051     3d/compare-eax-and 0/imm32/false
16052     75/jump-if-!= $check-no-tokens-left:end/disp8
16053     # if (slice-starts-with?(s, '#') return
16054     # . eax = *s->start
16055     8b/-> *edx 0/r32/eax
16056     8a/copy-byte *eax 0/r32/AL
16057     81 4/subop/and %eax 0xff/imm32
16058     # . if (eax == '#') continue
16059     3d/compare-eax-and 0x23/imm32/hash
16060     74/jump-if-= $check-no-tokens-left:end/disp8
16061     # abort
16062     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
16063     (rewind-stream %ecx)
16064     (write-stream 2 %ecx)
16065     (write-buffered Stderr "'\n")
16066     (flush Stderr)
16067     # . syscall(exit, 1)
16068     bb/copy-to-ebx  1/imm32
16069     e8/call syscall_exit/disp32
16070     # never gets here
16071 $check-no-tokens-left:end:
16072     # . reclaim locals
16073     81 0/subop/add %esp 8/imm32
16074     # . restore registers
16075     59/pop-to-ecx
16076     58/pop-to-eax
16077     # . epilogue
16078     89/<- %esp 5/r32/ebp
16079     5d/pop-to-ebp
16080     c3/return
16081 
16082 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)
16083     # pseudocode:
16084     #   var v: (handle var)
16085     #   new-literal(name, v)
16086     #   push(vars, {v, false})
16087     #   parse-mu-block(in, vars, fn, out)
16088     #   pop(vars)
16089     #   out->tag = block
16090     #   out->var = v
16091     #
16092     # . prologue
16093     55/push-ebp
16094     89/<- %ebp 4/r32/esp
16095     # . save registers
16096     50/push-eax
16097     51/push-ecx
16098     57/push-edi
16099     # var v/ecx: (handle var)
16100     68/push 0/imm32
16101     68/push 0/imm32
16102     89/<- %ecx 4/r32/esp
16103     #
16104     (new-literal Heap *(ebp+8) %ecx)
16105     # push(vars, v)
16106     (push *(ebp+0x10) *ecx)
16107     (push *(ebp+0x10) *(ecx+4))
16108     (push *(ebp+0x10) 0)  # false
16109     #
16110     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
16111     # pop v off vars
16112     (pop *(ebp+0x10))  # => eax
16113     (pop *(ebp+0x10))  # => eax
16114     (pop *(ebp+0x10))  # => eax
16115     # var out-addr/edi: (addr stmt) = lookup(*out)
16116     8b/-> *(ebp+0x18) 7/r32/edi
16117     (lookup *edi *(edi+4))  # => eax
16118     89/<- %edi 0/r32/eax
16119     # out-addr->tag = named-block
16120     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
16121     # out-addr->var = v
16122     8b/-> *ecx 0/r32/eax
16123     89/<- *(edi+0xc) 0/r32/eax  # Block-var
16124     8b/-> *(ecx+4) 0/r32/eax
16125     89/<- *(edi+0x10) 0/r32/eax  # Block-var
16126 $parse-mu-named-block:end:
16127     # . reclaim locals
16128     81 0/subop/add %esp 8/imm32
16129     # . restore registers
16130     5f/pop-to-edi
16131     59/pop-to-ecx
16132     58/pop-to-eax
16133     # . epilogue
16134     89/<- %esp 5/r32/ebp
16135     5d/pop-to-ebp
16136     c3/return
16137 
16138 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)
16139     # . prologue
16140     55/push-ebp
16141     89/<- %ebp 4/r32/esp
16142     # . save registers
16143     50/push-eax
16144     51/push-ecx
16145     52/push-edx
16146     53/push-ebx
16147     57/push-edi
16148     # edi = out
16149     8b/-> *(ebp+0x10) 7/r32/edi
16150     # var word-slice/ecx: slice
16151     68/push 0/imm32/end
16152     68/push 0/imm32/start
16153     89/<- %ecx 4/r32/esp
16154     # var v/edx: (handle var)
16155     68/push 0/imm32
16156     68/push 0/imm32
16157     89/<- %edx 4/r32/esp
16158     # v = parse-var-with-type(next-mu-token(line))
16159     (next-mu-token *(ebp+8) %ecx)
16160     (parse-var-with-type %ecx *(ebp+8) %edx *(ebp+0x18) *(ebp+0x1c))
16161     # var v-addr/eax: (addr var)
16162     (lookup *edx *(edx+4))  # => eax
16163     # v->block-depth = *Curr-block-depth
16164     8b/-> *Curr-block-depth 3/r32/ebx
16165     89/<- *(eax+0x10) 3/r32/ebx  # Var-block-depth
16166     # either v has no register and there's no more to this line
16167     8b/-> *(eax+0x18) 0/r32/eax  # Var-register
16168     3d/compare-eax-and 0/imm32
16169     {
16170       75/jump-if-!= break/disp8
16171       # TODO: disallow vars of type 'byte' on the stack
16172       # ensure that there's nothing else on this line
16173       (next-mu-token *(ebp+8) %ecx)
16174       (slice-empty? %ecx)  # => eax
16175       3d/compare-eax-and 0/imm32/false
16176       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
16177       #
16178       (new-var-def Heap  *edx *(edx+4)  %edi)
16179       e9/jump $parse-mu-var-def:update-vars/disp32
16180     }
16181     # or v has a register and there's more to this line
16182     {
16183       0f 84/jump-if-= break/disp32
16184       # TODO: disallow vars of type 'byte' in registers 'esi' or 'edi'
16185       # TODO: vars of type 'byte' should only be initialized by clearing to 0
16186       # ensure that the next word is '<-'
16187       (next-mu-token *(ebp+8) %ecx)
16188       (slice-equal? %ecx "<-")  # => eax
16189       3d/compare-eax-and 0/imm32/false
16190       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
16191       #
16192       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
16193       (lookup *edi *(edi+4))  # => eax
16194       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16195     }
16196 $parse-mu-var-def:update-vars:
16197     # push 'v' at end of function
16198     (push *(ebp+0xc) *edx)
16199     (push *(ebp+0xc) *(edx+4))
16200     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
16201 $parse-mu-var-def:end:
16202     # . reclaim locals
16203     81 0/subop/add %esp 0x10/imm32
16204     # . restore registers
16205     5f/pop-to-edi
16206     5b/pop-to-ebx
16207     5a/pop-to-edx
16208     59/pop-to-ecx
16209     58/pop-to-eax
16210     # . epilogue
16211     89/<- %esp 5/r32/ebp
16212     5d/pop-to-ebp
16213     c3/return
16214 
16215 $parse-mu-var-def:error1:
16216     (rewind-stream *(ebp+8))
16217     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
16218     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
16219     (flush *(ebp+0x18))
16220     (write-stream-data *(ebp+0x18) *(ebp+8))
16221     (write-buffered *(ebp+0x18) "'\n")
16222     (flush *(ebp+0x18))
16223     (stop *(ebp+0x1c) 1)
16224     # never gets here
16225 
16226 $parse-mu-var-def:error2:
16227     (rewind-stream *(ebp+8))
16228     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
16229     (write-buffered *(ebp+0x18) "fn ")
16230     8b/-> *(ebp+0x14) 0/r32/eax
16231     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16232     (write-buffered *(ebp+0x18) %eax)
16233     (write-buffered *(ebp+0x18) ": var ")
16234     # var v-addr/eax: (addr var) = lookup(v)
16235     (lookup *edx *(edx+4))  # => eax
16236     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16237     (write-buffered *(ebp+0x18) %eax)
16238     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
16239     (flush *(ebp+0x18))
16240     (stop *(ebp+0x1c) 1)
16241     # never gets here
16242 
16243 test-parse-mu-var-def:
16244     # 'var n: int'
16245     # . prologue
16246     55/push-ebp
16247     89/<- %ebp 4/r32/esp
16248     # setup
16249     8b/-> *Primitive-type-ids 0/r32/eax
16250     89/<- *Type-id 0/r32/eax  # stream-write
16251     (clear-stream _test-input-stream)
16252     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
16253     c7 0/subop/copy *Curr-block-depth 1/imm32
16254     # var out/esi: (handle stmt)
16255     68/push 0/imm32
16256     68/push 0/imm32
16257     89/<- %esi 4/r32/esp
16258     # var vars/ecx: (stack (addr var) 16)
16259     81 5/subop/subtract %esp 0xc0/imm32
16260     68/push 0xc0/imm32/size
16261     68/push 0/imm32/top
16262     89/<- %ecx 4/r32/esp
16263     (clear-stack %ecx)
16264     # convert
16265     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
16266     # var out-addr/esi: (addr stmt)
16267     (lookup *esi *(esi+4))  # => eax
16268     89/<- %esi 0/r32/eax
16269     #
16270     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
16271     # var v/ecx: (addr var) = lookup(out->var)
16272     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
16273     89/<- %ecx 0/r32/eax
16274     # v->name
16275     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16276     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
16277     # v->register
16278     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
16279     # v->block-depth
16280     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
16281     # v->type == int
16282     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16283     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
16284     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
16285     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
16286     # . epilogue
16287     89/<- %esp 5/r32/ebp
16288     5d/pop-to-ebp
16289     c3/return
16290 
16291 test-parse-mu-reg-var-def:
16292     # 'var n/eax: int <- copy 0'
16293     # . prologue
16294     55/push-ebp
16295     89/<- %ebp 4/r32/esp
16296     # setup
16297     8b/-> *Primitive-type-ids 0/r32/eax
16298     89/<- *Type-id 0/r32/eax  # stream-write
16299     (clear-stream _test-input-stream)
16300     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
16301     c7 0/subop/copy *Curr-block-depth 1/imm32
16302     # var out/esi: (handle stmt)
16303     68/push 0/imm32
16304     68/push 0/imm32
16305     89/<- %esi 4/r32/esp
16306     # var vars/ecx: (stack (addr var) 16)
16307     81 5/subop/subtract %esp 0xc0/imm32
16308     68/push 0xc0/imm32/size
16309     68/push 0/imm32/top
16310     89/<- %ecx 4/r32/esp
16311     (clear-stack %ecx)
16312     # convert
16313     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
16314     # var out-addr/esi: (addr stmt)
16315     (lookup *esi *(esi+4))  # => eax
16316     89/<- %esi 0/r32/eax
16317     #
16318     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
16319     # var v/ecx: (addr var) = lookup(out->outputs->value)
16320     # . eax: (addr stmt-var) = lookup(out->outputs)
16321     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
16322     # .
16323     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
16324     # . eax: (addr var) = lookup(eax->value)
16325     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16326     # . ecx = eax
16327     89/<- %ecx 0/r32/eax
16328     # v->name
16329     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16330     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
16331     # v->register
16332     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
16333     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
16334     # v->block-depth
16335     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
16336     # v->type == int
16337     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16338     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
16339     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
16340     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
16341     # . epilogue
16342     89/<- %esp 5/r32/ebp
16343     5d/pop-to-ebp
16344     c3/return
16345 
16346 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)
16347     # pseudocode:
16348     #   var name: slice
16349     #   allocate(Heap, Stmt-size, out)
16350     #   var out-addr: (addr stmt) = lookup(*out)
16351     #   out-addr->tag = stmt
16352     #   if stmt-has-outputs?(line)
16353     #     while true
16354     #       name = next-mu-token(line)
16355     #       if (name == '<-') break
16356     #       assert(is-identifier?(name))
16357     #       var v: (handle var) = lookup-var(name, vars)
16358     #       out-addr->outputs = append(v, out-addr->outputs)
16359     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
16360     #
16361     # . prologue
16362     55/push-ebp
16363     89/<- %ebp 4/r32/esp
16364     # . save registers
16365     50/push-eax
16366     51/push-ecx
16367     52/push-edx
16368     53/push-ebx
16369     57/push-edi
16370     # var name/ecx: slice
16371     68/push 0/imm32/end
16372     68/push 0/imm32/start
16373     89/<- %ecx 4/r32/esp
16374     # var is-deref?/edx: boolean = false
16375     ba/copy-to-edx 0/imm32/false
16376     # var v: (handle var)
16377     68/push 0/imm32
16378     68/push 0/imm32
16379     89/<- %ebx 4/r32/esp
16380     #
16381     (allocate Heap *Stmt-size *(ebp+0x14))
16382     # var out-addr/edi: (addr stmt) = lookup(*out)
16383     8b/-> *(ebp+0x14) 7/r32/edi
16384     (lookup *edi *(edi+4))  # => eax
16385     89/<- %edi 0/r32/eax
16386     # out-addr->tag = 1/stmt
16387     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
16388     {
16389       (stmt-has-outputs? *(ebp+8))
16390       3d/compare-eax-and 0/imm32/false
16391       0f 84/jump-if-= break/disp32
16392       {
16393 $parse-mu-stmt:read-outputs:
16394         # name = next-mu-token(line)
16395         (next-mu-token *(ebp+8) %ecx)
16396         # if slice-empty?(word-slice) break
16397         (slice-empty? %ecx)  # => eax
16398         3d/compare-eax-and 0/imm32/false
16399         0f 85/jump-if-!= break/disp32
16400         # if (name == "<-") break
16401         (slice-equal? %ecx "<-")  # => eax
16402         3d/compare-eax-and 0/imm32/false
16403         0f 85/jump-if-!= break/disp32
16404         # is-deref? = false
16405         ba/copy-to-edx 0/imm32/false
16406         # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
16407         8b/-> *ecx 0/r32/eax  # Slice-start
16408         8a/copy-byte *eax 0/r32/AL
16409         81 4/subop/and %eax 0xff/imm32
16410         3d/compare-eax-and 0x2a/imm32/asterisk
16411         {
16412           75/jump-if-!= break/disp8
16413           ff 0/subop/increment *ecx
16414           ba/copy-to-edx 1/imm32/true
16415         }
16416         # assert(is-identifier?(name))
16417         (is-identifier? %ecx)  # => eax
16418         3d/compare-eax-and 0/imm32/false
16419         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
16420         #
16421         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
16422         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
16423         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  %edx  %eax)  # Stmt1-outputs
16424         #
16425         e9/jump loop/disp32
16426       }
16427     }
16428     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
16429 $parse-mu-stmt:end:
16430     # . reclaim locals
16431     81 0/subop/add %esp 0x10/imm32
16432     # . restore registers
16433     5f/pop-to-edi
16434     5b/pop-to-ebx
16435     5a/pop-to-edx
16436     59/pop-to-ecx
16437     58/pop-to-eax
16438     # . epilogue
16439     89/<- %esp 5/r32/ebp
16440     5d/pop-to-ebp
16441     c3/return
16442 
16443 $parse-mu-stmt:abort:
16444     # error("invalid identifier '" name "'\n")
16445     (write-buffered *(ebp+0x18) "invalid identifier '")
16446     (write-slice-buffered *(ebp+0x18) %ecx)
16447     (write-buffered *(ebp+0x18) "'\n")
16448     (flush *(ebp+0x18))
16449     (stop *(ebp+0x1c) 1)
16450     # never gets here
16451 
16452 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)
16453     # pseudocode:
16454     #   stmt->name = slice-to-string(next-mu-token(line))
16455     #   while true
16456     #     name = next-mu-token(line)
16457     #     v = lookup-var-or-literal(name)
16458     #     stmt->inouts = append(v, stmt->inouts)
16459     #
16460     # . prologue
16461     55/push-ebp
16462     89/<- %ebp 4/r32/esp
16463     # . save registers
16464     50/push-eax
16465     51/push-ecx
16466     52/push-edx
16467     53/push-ebx
16468     56/push-esi
16469     57/push-edi
16470     # edi = stmt
16471     8b/-> *(ebp+8) 7/r32/edi
16472     # var name/ecx: slice
16473     68/push 0/imm32/end
16474     68/push 0/imm32/start
16475     89/<- %ecx 4/r32/esp
16476     # var is-deref?/edx: boolean = false
16477     ba/copy-to-edx 0/imm32/false
16478     # var v/esi: (handle var)
16479     68/push 0/imm32
16480     68/push 0/imm32
16481     89/<- %esi 4/r32/esp
16482 $add-operation-and-inputs-to-stmt:read-operation:
16483     (next-mu-token *(ebp+0xc) %ecx)
16484     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
16485     (slice-to-string Heap %ecx %eax)
16486     # var is-get?/ebx: boolean = (name == "get")
16487     (slice-equal? %ecx "get")  # => eax
16488     89/<- %ebx 0/r32/eax
16489     {
16490 $add-operation-and-inputs-to-stmt:read-inouts:
16491       # name = next-mu-token(line)
16492       (next-mu-token *(ebp+0xc) %ecx)
16493       # if slice-empty?(word-slice) break
16494       (slice-empty? %ecx)  # => eax
16495       3d/compare-eax-and 0/imm32/false
16496       0f 85/jump-if-!= break/disp32
16497       # if (name == "<-") abort
16498       (slice-equal? %ecx "<-")
16499       3d/compare-eax-and 0/imm32/false
16500       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
16501       # if (is-get? && second operand) lookup or create offset
16502       {
16503         81 7/subop/compare %ebx 0/imm32/false
16504         74/jump-if-= break/disp8
16505         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16506         3d/compare-eax-and 0/imm32
16507         74/jump-if-= break/disp8
16508         (lookup-or-create-constant %eax %ecx %esi)
16509 #?         (lookup *esi *(esi+4))
16510 #?         (write-buffered Stderr "creating new output var ")
16511 #?         (write-int32-hex-buffered Stderr %eax)
16512 #?         (write-buffered Stderr " for field called ")
16513 #?         (write-slice-buffered Stderr %ecx)
16514 #?         (write-buffered Stderr "; var name ")
16515 #?         (lookup *eax *(eax+4))  # Var-name
16516 #?         (write-buffered Stderr %eax)
16517 #?         (write-buffered Stderr Newline)
16518 #?         (flush Stderr)
16519         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
16520       }
16521       # is-deref? = false
16522       ba/copy-to-edx 0/imm32/false
16523       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
16524       8b/-> *ecx 0/r32/eax  # Slice-start
16525       8a/copy-byte *eax 0/r32/AL
16526       81 4/subop/and %eax 0xff/imm32
16527       3d/compare-eax-and 0x2a/imm32/asterisk
16528       {
16529         75/jump-if-!= break/disp8
16530 $add-operation-and-inputs-to-stmt:inout-is-deref:
16531         ff 0/subop/increment *ecx
16532         ba/copy-to-edx 1/imm32/true
16533       }
16534       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16535       # if (is-deref?) some additional checks
16536       81 7/subop/compare %edx 0/imm32/false
16537       {
16538         74/jump-if-= break/disp8
16539         # if var is not in register, abort
16540         (lookup *esi *(esi+4))  # => eax
16541         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16542         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
16543         # if var is not an address, abort
16544         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16545         (is-mu-addr-type? %eax)  # => eax
16546         3d/compare-eax-and 0/imm32/false
16547         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
16548       }
16549 $add-operation-and-inputs-to-stmt:save-var:
16550       8d/copy-address *(edi+0xc) 0/r32/eax
16551       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
16552       #
16553       e9/jump loop/disp32
16554     }
16555 $add-operation-and-inputs-to-stmt:end:
16556     # . reclaim locals
16557     81 0/subop/add %esp 0x10/imm32
16558     # . restore registers
16559     5f/pop-to-edi
16560     5e/pop-to-esi
16561     5b/pop-to-ebx
16562     5a/pop-to-edx
16563     59/pop-to-ecx
16564     58/pop-to-eax
16565     # . epilogue
16566     89/<- %esp 5/r32/ebp
16567     5d/pop-to-ebp
16568     c3/return
16569 
16570 $add-operation-and-inputs-to-stmt:abort:
16571     # error("fn ___: invalid identifier in '" line "'\n")
16572     (write-buffered *(ebp+0x18) "fn ")
16573     8b/-> *(ebp+0x14) 0/r32/eax
16574     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16575     (write-buffered *(ebp+0x18) %eax)
16576     (rewind-stream *(ebp+0xc))
16577     (write-buffered *(ebp+0x18) ": invalid identifier in '")
16578     (write-stream-data *(ebp+0x18) *(ebp+0xc))
16579     (write-buffered *(ebp+0x18) "'\n")
16580     (flush *(ebp+0x18))
16581     (stop *(ebp+0x1c) 1)
16582     # never gets here
16583 
16584 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
16585     # error("fn ___: cannot dereference var ___ on stack\n")
16586     (write-buffered *(ebp+0x18) "fn ")
16587     8b/-> *(ebp+0x14) 0/r32/eax
16588     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16589     (write-buffered *(ebp+0x18) %eax)
16590     (rewind-stream *(ebp+0xc))
16591     (write-buffered *(ebp+0x18) ": cannot dereference var '")
16592     (lookup *esi *(esi+4))  # => eax
16593     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16594     (write-buffered *(ebp+0x18) %eax)
16595     (write-buffered *(ebp+0x18) "' on stack\n")
16596     (flush *(ebp+0x18))
16597     (stop *(ebp+0x1c) 1)
16598     # never gets here
16599 
16600 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
16601     # error("fn ___: cannot dereference non-addr var ___\n")
16602     (write-buffered *(ebp+0x18) "fn ")
16603     8b/-> *(ebp+0x14) 0/r32/eax
16604     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16605     (write-buffered *(ebp+0x18) %eax)
16606     (rewind-stream *(ebp+0xc))
16607     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
16608     (lookup *esi *(esi+4))  # => eax
16609     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16610     (write-buffered *(ebp+0x18) %eax)
16611     (write-buffered *(ebp+0x18) "'\n")
16612     (flush *(ebp+0x18))
16613     (stop *(ebp+0x1c) 1)
16614     # never gets here
16615 
16616 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
16617     # . prologue
16618     55/push-ebp
16619     89/<- %ebp 4/r32/esp
16620     # . save registers
16621     51/push-ecx
16622     # var word-slice/ecx: slice
16623     68/push 0/imm32/end
16624     68/push 0/imm32/start
16625     89/<- %ecx 4/r32/esp
16626     # result = false
16627     b8/copy-to-eax 0/imm32/false
16628     (rewind-stream *(ebp+8))
16629     {
16630       (next-mu-token *(ebp+8) %ecx)
16631       # if slice-empty?(word-slice) break
16632       (slice-empty? %ecx)
16633       3d/compare-eax-and 0/imm32/false
16634       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
16635       0f 85/jump-if-!= break/disp32
16636       # if slice-starts-with?(word-slice, '#') break
16637       # . eax = *word-slice->start
16638       8b/-> *ecx 0/r32/eax
16639       8a/copy-byte *eax 0/r32/AL
16640       81 4/subop/and %eax 0xff/imm32
16641       # . if (eax == '#') break
16642       3d/compare-eax-and 0x23/imm32/hash
16643       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
16644       0f 84/jump-if-= break/disp32
16645       # if slice-equal?(word-slice, '<-') return true
16646       (slice-equal? %ecx "<-")
16647       3d/compare-eax-and 0/imm32/false
16648       74/jump-if-= loop/disp8
16649       b8/copy-to-eax 1/imm32/true
16650     }
16651 $stmt-has-outputs:end:
16652     (rewind-stream *(ebp+8))
16653     # . reclaim locals
16654     81 0/subop/add %esp 8/imm32
16655     # . restore registers
16656     59/pop-to-ecx
16657     # . epilogue
16658     89/<- %esp 5/r32/ebp
16659     5d/pop-to-ebp
16660     c3/return
16661 
16662 # if 'name' starts with a digit, create a new literal var for it
16663 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
16664 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)
16665     # . prologue
16666     55/push-ebp
16667     89/<- %ebp 4/r32/esp
16668     # . save registers
16669     50/push-eax
16670     51/push-ecx
16671     56/push-esi
16672     # esi = name
16673     8b/-> *(ebp+8) 6/r32/esi
16674     # if slice-empty?(name) abort
16675     (slice-empty? %esi)  # => eax
16676     3d/compare-eax-and 0/imm32/false
16677     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
16678     # var c/ecx: byte = *name->start
16679     8b/-> *esi 1/r32/ecx
16680     8a/copy-byte *ecx 1/r32/CL
16681     81 4/subop/and %ecx 0xff/imm32
16682     # if (is-decimal-digit?(c) || c == '-') return new var(name)
16683     {
16684       81 7/subop/compare %ecx 0x2d/imm32/dash
16685       74/jump-if-= $lookup-var-or-literal:literal/disp8
16686       (is-decimal-digit? %ecx)  # => eax
16687       3d/compare-eax-and 0/imm32/false
16688       74/jump-if-= break/disp8
16689 $lookup-var-or-literal:literal:
16690       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16691       eb/jump $lookup-var-or-literal:end/disp8
16692     }
16693     # else if (c == '"') return new var(name)
16694     {
16695       81 7/subop/compare %ecx 0x22/imm32/dquote
16696       75/jump-if-!= break/disp8
16697 $lookup-var-or-literal:literal-string:
16698       (new-literal-string Heap %esi *(ebp+0x10))
16699       eb/jump $lookup-var-or-literal:end/disp8
16700     }
16701     # otherwise return lookup-var(name, vars)
16702     {
16703 $lookup-var-or-literal:var:
16704       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16705     }
16706 $lookup-var-or-literal:end:
16707     # . restore registers
16708     5e/pop-to-esi
16709     59/pop-to-ecx
16710     58/pop-to-eax
16711     # . epilogue
16712     89/<- %esp 5/r32/ebp
16713     5d/pop-to-ebp
16714     c3/return
16715 
16716 $lookup-var-or-literal:abort:
16717     (write-buffered *(ebp+0x18) "fn ")
16718     8b/-> *(ebp+0x14) 0/r32/eax
16719     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16720     (write-buffered *(ebp+0x18) %eax)
16721     (write-buffered *(ebp+0x18) ": empty variable!")
16722     (flush *(ebp+0x18))
16723     (stop *(ebp+0x1c) 1)
16724     # never gets here
16725 
16726 # return first 'name' from the top (back) of 'vars' and abort if not found
16727 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)
16728     # . prologue
16729     55/push-ebp
16730     89/<- %ebp 4/r32/esp
16731     # . save registers
16732     50/push-eax
16733     #
16734     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
16735     # if (*out == 0) abort
16736     8b/-> *(ebp+0x10) 0/r32/eax
16737     81 7/subop/compare *eax 0/imm32
16738     74/jump-if-= $lookup-var:abort/disp8
16739 $lookup-var:end:
16740     # . restore registers
16741     58/pop-to-eax
16742     # . epilogue
16743     89/<- %esp 5/r32/ebp
16744     5d/pop-to-ebp
16745     c3/return
16746 
16747 $lookup-var:abort:
16748     (write-buffered *(ebp+0x18) "fn ")
16749     8b/-> *(ebp+0x14) 0/r32/eax
16750     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16751     (write-buffered *(ebp+0x18) %eax)
16752     (write-buffered *(ebp+0x18) ": unknown variable '")
16753     (write-slice-buffered *(ebp+0x18) *(ebp+8))
16754     (write-buffered *(ebp+0x18) "'\n")
16755     (flush *(ebp+0x18))
16756     (stop *(ebp+0x1c) 1)
16757     # never gets here
16758 
16759 # return first 'name' from the top (back) of 'vars', and 0/null if not found
16760 # ensure that 'name' if in a register is the topmost variable in that register
16761 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)
16762     # pseudocode:
16763     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
16764     #   var min = vars->data
16765     #   while curr >= min
16766     #     var v: (handle var) = *curr
16767     #     if v->name == name
16768     #       return
16769     #     curr -= 12
16770     #
16771     # . prologue
16772     55/push-ebp
16773     89/<- %ebp 4/r32/esp
16774     # . save registers
16775     50/push-eax
16776     51/push-ecx
16777     52/push-edx
16778     53/push-ebx
16779     56/push-esi
16780     57/push-edi
16781     # clear out
16782     (zero-out *(ebp+0x10) *Handle-size)
16783     # esi = vars
16784     8b/-> *(ebp+0xc) 6/r32/esi
16785     # ebx = vars->top
16786     8b/-> *esi 3/r32/ebx
16787     # if (vars->top > vars->size) abort
16788     3b/compare<- *(esi+4) 0/r32/eax
16789     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
16790     # var min/edx: (addr handle var) = vars->data
16791     8d/copy-address *(esi+8) 2/r32/edx
16792     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
16793     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
16794     # var var-in-reg/edi: 16 addrs
16795     68/push 0/imm32
16796     68/push 0/imm32
16797     68/push 0/imm32
16798     68/push 0/imm32
16799     68/push 0/imm32
16800     68/push 0/imm32
16801     68/push 0/imm32
16802     68/push 0/imm32
16803     68/push 0/imm32
16804     68/push 0/imm32
16805     68/push 0/imm32
16806     68/push 0/imm32
16807     68/push 0/imm32
16808     68/push 0/imm32
16809     68/push 0/imm32
16810     68/push 0/imm32
16811     89/<- %edi 4/r32/esp
16812     {
16813 $lookup-var-helper:loop:
16814       # if (curr < min) return
16815       39/compare %ebx 2/r32/edx
16816       0f 82/jump-if-addr< break/disp32
16817       # var v/ecx: (addr var) = lookup(*curr)
16818       (lookup *ebx *(ebx+4))  # => eax
16819       89/<- %ecx 0/r32/eax
16820       # var vn/eax: (addr array byte) = lookup(v->name)
16821       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16822       # if (vn == name) return curr
16823       (slice-equal? *(ebp+8) %eax)  # => eax
16824       3d/compare-eax-and 0/imm32/false
16825       {
16826         74/jump-if-= break/disp8
16827 $lookup-var-helper:found:
16828         # var vr/eax: (addr array byte) = lookup(v->register)
16829         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
16830         3d/compare-eax-and 0/imm32
16831         {
16832           74/jump-if-= break/disp8
16833 $lookup-var-helper:found-register:
16834           # var reg/eax: int = get(Registers, vr)
16835           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
16836           8b/-> *eax 0/r32/eax
16837           # if (var-in-reg[reg]) error
16838           8b/-> *(edi+eax<<2) 0/r32/eax
16839           3d/compare-eax-and 0/imm32
16840           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
16841         }
16842 $lookup-var-helper:return:
16843         # esi = out
16844         8b/-> *(ebp+0x10) 6/r32/esi
16845         # *out = *curr
16846         8b/-> *ebx 0/r32/eax
16847         89/<- *esi 0/r32/eax
16848         8b/-> *(ebx+4) 0/r32/eax
16849         89/<- *(esi+4) 0/r32/eax
16850         # return
16851         eb/jump $lookup-var-helper:end/disp8
16852       }
16853       # 'name' not yet found; update var-in-reg if v in register
16854       # . var vr/eax: (addr array byte) = lookup(v->register)
16855       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
16856       # . if (vr == 0) continue
16857       3d/compare-eax-and 0/imm32
16858       74/jump-if-= $lookup-var-helper:continue/disp8
16859       # . var reg/eax: int = get(Registers, vr)
16860       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
16861       8b/-> *eax 0/r32/eax
16862       # . var-in-reg[reg] = v
16863       89/<- *(edi+eax<<2) 1/r32/ecx
16864 $lookup-var-helper:continue:
16865       # curr -= 12
16866       81 5/subop/subtract %ebx 0xc/imm32
16867       e9/jump loop/disp32
16868     }
16869 $lookup-var-helper:end:
16870     # . reclaim locals
16871     81 0/subop/add %esp 0x40/imm32
16872     # . restore registers
16873     5f/pop-to-edi
16874     5e/pop-to-esi
16875     5b/pop-to-ebx
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 $lookup-var-helper:error1:
16885     (write-buffered *(ebp+0x18) "fn ")
16886     8b/-> *(ebp+0x14) 0/r32/eax
16887     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16888     (write-buffered *(ebp+0x18) %eax)
16889     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
16890     (write-slice-buffered *(ebp+0x18) *(ebp+8))
16891     (write-buffered *(ebp+0x18) "'\n")
16892     (flush *(ebp+0x18))
16893     (stop *(ebp+0x1c) 1)
16894     # never gets here
16895 
16896 $lookup-var-helper:error2:
16897     # eax contains the conflicting var at this point
16898     (write-buffered *(ebp+0x18) "fn ")
16899     50/push-eax
16900     8b/-> *(ebp+0x14) 0/r32/eax
16901     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16902     (write-buffered *(ebp+0x18) %eax)
16903     58/pop-eax
16904     (write-buffered *(ebp+0x18) ": register ")
16905     50/push-eax
16906     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16907     (write-buffered *(ebp+0x18) %eax)
16908     58/pop-to-eax
16909     (write-buffered *(ebp+0x18) " reads var '")
16910     (write-slice-buffered *(ebp+0x18) *(ebp+8))
16911     (write-buffered *(ebp+0x18) "' after writing var '")
16912     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16913     (write-buffered *(ebp+0x18) %eax)
16914     (write-buffered *(ebp+0x18) "'\n")
16915     (flush *(ebp+0x18))
16916     (stop *(ebp+0x1c) 1)
16917     # never gets here
16918 
16919 dump-vars:  # vars: (addr stack live-var)
16920     # pseudocode:
16921     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
16922     #   var min = vars->data
16923     #   while curr >= min
16924     #     var v: (handle var) = *curr
16925     #     print v
16926     #     curr -= 12
16927     #
16928     # . prologue
16929     55/push-ebp
16930     89/<- %ebp 4/r32/esp
16931     # . save registers
16932     52/push-edx
16933     53/push-ebx
16934     56/push-esi
16935     # esi = vars
16936     8b/-> *(ebp+8) 6/r32/esi
16937     # ebx = vars->top
16938     8b/-> *esi 3/r32/ebx
16939     # var min/edx: (addr handle var) = vars->data
16940     8d/copy-address *(esi+8) 2/r32/edx
16941     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
16942     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
16943     {
16944 $dump-vars:loop:
16945       # if (curr < min) return
16946       39/compare %ebx 2/r32/edx
16947       0f 82/jump-if-addr< break/disp32
16948       #
16949       (write-buffered Stderr "  var@")
16950       (dump-var 2 %ebx)
16951       # curr -= 12
16952       81 5/subop/subtract %ebx 0xc/imm32
16953       e9/jump loop/disp32
16954     }
16955 $dump-vars:end:
16956     # . restore registers
16957     5e/pop-to-esi
16958     5b/pop-to-ebx
16959     5a/pop-to-edx
16960     # . epilogue
16961     89/<- %esp 5/r32/ebp
16962     5d/pop-to-ebp
16963     c3/return
16964 
16965 == data
16966 # Like Registers, but no esp or ebp
16967 Mu-registers:  # (addr stream {(handle array byte), int})
16968   # a table is a stream
16969   0xa8/imm32/write
16970   0/imm32/read
16971   0xa8/imm32/length
16972   # data
16973   # general-purpose registers
16974   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
16975   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
16976   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
16977   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
16978   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
16979   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
16980   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
16981   # floating-point registers
16982   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
16983   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
16984   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
16985   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
16986   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
16987   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
16988   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
16989   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
16990 
16991 # Like Mu-registers, but with unique codes for integer and floating-point
16992 # registers.
16993 # Don't use this for code-generation, only for checking.
16994 Mu-registers-unique:  # (addr stream {(handle array byte), int})
16995   # a table is a stream
16996   0xa8/imm32/write
16997   0/imm32/read
16998   0xa8/imm32/length
16999   # data
17000   # general-purpose registers
17001   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
17002   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
17003   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
17004   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
17005   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
17006   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
17007   # floating-point registers
17008   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
17009   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
17010   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
17011   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
17012   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
17013   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
17014   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
17015   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
17016 
17017 $Mu-register-eax:
17018   0x11/imm32/alloc-id
17019   3/imm32/size
17020   0x65/e 0x61/a 0x78/x
17021 
17022 $Mu-register-ecx:
17023   0x11/imm32/alloc-id
17024   3/imm32/size
17025   0x65/e 0x63/c 0x78/x
17026 
17027 $Mu-register-edx:
17028   0x11/imm32/alloc-id
17029   3/imm32/size
17030   0x65/e 0x64/d 0x78/x
17031 
17032 $Mu-register-ebx:
17033   0x11/imm32/alloc-id
17034   3/imm32/size
17035   0x65/e 0x62/b 0x78/x
17036 
17037 $Mu-register-esi:
17038   0x11/imm32/alloc-id
17039   3/imm32/size
17040   0x65/e 0x73/s 0x69/i
17041 
17042 $Mu-register-edi:
17043   0x11/imm32/alloc-id
17044   3/imm32/size
17045   0x65/e 0x64/d 0x69/i
17046 
17047 $Mu-register-xmm0:
17048   0x11/imm32/alloc-id:fake:payload
17049   # "xmm0"
17050   0x4/imm32/size
17051   0x78/x 0x6d/m 0x6d/m 0x30/0
17052 
17053 $Mu-register-xmm1:
17054   0x11/imm32/alloc-id:fake:payload
17055   # "xmm1"
17056   0x4/imm32/size
17057   0x78/x 0x6d/m 0x6d/m 0x31/1
17058 
17059 $Mu-register-xmm2:
17060   0x11/imm32/alloc-id:fake:payload
17061   # "xmm2"
17062   0x4/imm32/size
17063   0x78/x 0x6d/m 0x6d/m 0x32/2
17064 
17065 $Mu-register-xmm3:
17066   0x11/imm32/alloc-id:fake:payload
17067   # "xmm3"
17068   0x4/imm32/size
17069   0x78/x 0x6d/m 0x6d/m 0x33/3
17070 
17071 $Mu-register-xmm4:
17072   0x11/imm32/alloc-id:fake:payload
17073   # "xmm4"
17074   0x4/imm32/size
17075   0x78/x 0x6d/m 0x6d/m 0x34/4
17076 
17077 $Mu-register-xmm5:
17078   0x11/imm32/alloc-id:fake:payload
17079   # "xmm5"
17080   0x4/imm32/size
17081   0x78/x 0x6d/m 0x6d/m 0x35/5
17082 
17083 $Mu-register-xmm6:
17084   0x11/imm32/alloc-id:fake:payload
17085   # "xmm6"
17086   0x4/imm32/size
17087   0x78/x 0x6d/m 0x6d/m 0x36/6
17088 
17089 $Mu-register-xmm7:
17090   0x11/imm32/alloc-id:fake:payload
17091   # "xmm7"
17092   0x4/imm32/size
17093   0x78/x 0x6d/m 0x6d/m 0x37/7
17094 
17095 == code
17096 
17097 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
17098 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
17099     # . prologue
17100     55/push-ebp
17101     89/<- %ebp 4/r32/esp
17102     # . save registers
17103     50/push-eax
17104     # var out-addr/eax: (addr var)
17105     (lookup *(ebp+8) *(ebp+0xc))  # => eax
17106     #
17107     (binding-exists? %eax *(ebp+0x10))  # => eax
17108     3d/compare-eax-and 0/imm32/false
17109     75/jump-if-!= $maybe-define-var:end/disp8
17110     # otherwise update vars
17111     (push *(ebp+0x10) *(ebp+8))
17112     (push *(ebp+0x10) *(ebp+0xc))
17113     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
17114 $maybe-define-var:end:
17115     # . restore registers
17116     58/pop-to-eax
17117     # . epilogue
17118     89/<- %esp 5/r32/ebp
17119     5d/pop-to-ebp
17120     c3/return
17121 
17122 # simpler version of lookup-var-helper
17123 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
17124     # pseudocode:
17125     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
17126     #   var min = vars->data
17127     #   while curr >= min
17128     #     var v: (handle var) = *curr
17129     #     if v->name == target->name
17130     #       return true
17131     #     curr -= 12
17132     #   return false
17133     #
17134     # . prologue
17135     55/push-ebp
17136     89/<- %ebp 4/r32/esp
17137     # . save registers
17138     51/push-ecx
17139     52/push-edx
17140     56/push-esi
17141     # var target-name/ecx: (addr array byte) = lookup(target->name)
17142     8b/-> *(ebp+8) 0/r32/eax
17143     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17144     89/<- %ecx 0/r32/eax
17145     # esi = vars
17146     8b/-> *(ebp+0xc) 6/r32/esi
17147     # eax = vars->top
17148     8b/-> *esi 0/r32/eax
17149     # var min/edx: (addr handle var) = vars->data
17150     8d/copy-address *(esi+8) 2/r32/edx
17151     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
17152     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
17153     {
17154 $binding-exists?:loop:
17155       # if (curr < min) return
17156       39/compare %esi 2/r32/edx
17157       0f 82/jump-if-addr< break/disp32
17158       # var v/eax: (addr var) = lookup(*curr)
17159       (lookup *esi *(esi+4))  # => eax
17160       # var vn/eax: (addr array byte) = lookup(v->name)
17161       (lookup *eax *(eax+4))  # Var-name Var-name => eax
17162       # if (vn == target-name) return true
17163       (string-equal? %ecx %eax)  # => eax
17164       3d/compare-eax-and 0/imm32/false
17165       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
17166       # curr -= 12
17167       81 5/subop/subtract %esi 0xc/imm32
17168       e9/jump loop/disp32
17169     }
17170     b8/copy-to-eax 0/imm32/false
17171 $binding-exists?:end:
17172     # . restore registers
17173     5e/pop-to-esi
17174     5a/pop-to-edx
17175     59/pop-to-ecx
17176     # . epilogue
17177     89/<- %esp 5/r32/ebp
17178     5d/pop-to-ebp
17179     c3/return
17180 
17181 test-parse-mu-stmt:
17182     # . prologue
17183     55/push-ebp
17184     89/<- %ebp 4/r32/esp
17185     # setup
17186     8b/-> *Primitive-type-ids 0/r32/eax
17187     89/<- *Type-id 0/r32/eax  # stream-write
17188     (clear-stream _test-input-stream)
17189     (write _test-input-stream "increment n\n")
17190     # var vars/ecx: (stack (addr var) 16)
17191     81 5/subop/subtract %esp 0xc0/imm32
17192     68/push 0xc0/imm32/size
17193     68/push 0/imm32/top
17194     89/<- %ecx 4/r32/esp
17195     (clear-stack %ecx)
17196     # var v/edx: (handle var)
17197     68/push 0/imm32
17198     68/push 0/imm32
17199     89/<- %edx 4/r32/esp
17200     # var s/eax: (handle array byte)
17201     68/push 0/imm32
17202     68/push 0/imm32
17203     89/<- %eax 4/r32/esp
17204     # v = new var("n")
17205     (copy-array Heap "n" %eax)
17206     (new-var Heap *eax *(eax+4) %edx)
17207     #
17208     (push %ecx *edx)
17209     (push %ecx *(edx+4))
17210     (push %ecx 0)
17211     # var out/eax: (handle stmt)
17212     68/push 0/imm32
17213     68/push 0/imm32
17214     89/<- %eax 4/r32/esp
17215     # convert
17216     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
17217     # var out-addr/edx: (addr stmt) = lookup(*out)
17218     (lookup *eax *(eax+4))  # => eax
17219     89/<- %edx 0/r32/eax
17220     # out->tag
17221     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
17222     # out->operation
17223     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
17224     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
17225     # out->inouts->value->name
17226     # . eax = out->inouts
17227     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17228     # . eax = out->inouts->value
17229     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17230     # . eax = out->inouts->value->name
17231     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17232     # .
17233     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
17234     # . epilogue
17235     89/<- %esp 5/r32/ebp
17236     5d/pop-to-ebp
17237     c3/return
17238 
17239 test-parse-mu-stmt-with-comma:
17240     # . prologue
17241     55/push-ebp
17242     89/<- %ebp 4/r32/esp
17243     # setup
17244     8b/-> *Primitive-type-ids 0/r32/eax
17245     89/<- *Type-id 0/r32/eax  # stream-write
17246     (clear-stream _test-input-stream)
17247     (write _test-input-stream "copy-to n, 3\n")
17248     # var vars/ecx: (stack (addr var) 16)
17249     81 5/subop/subtract %esp 0xc0/imm32
17250     68/push 0xc0/imm32/size
17251     68/push 0/imm32/top
17252     89/<- %ecx 4/r32/esp
17253     (clear-stack %ecx)
17254     # var v/edx: (handle var)
17255     68/push 0/imm32
17256     68/push 0/imm32
17257     89/<- %edx 4/r32/esp
17258     # var s/eax: (handle array byte)
17259     68/push 0/imm32
17260     68/push 0/imm32
17261     89/<- %eax 4/r32/esp
17262     # v = new var("n")
17263     (copy-array Heap "n" %eax)
17264     (new-var Heap *eax *(eax+4) %edx)
17265     #
17266     (push %ecx *edx)
17267     (push %ecx *(edx+4))
17268     (push %ecx 0)
17269     # var out/eax: (handle stmt)
17270     68/push 0/imm32
17271     68/push 0/imm32
17272     89/<- %eax 4/r32/esp
17273     # convert
17274     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
17275     # var out-addr/edx: (addr stmt) = lookup(*out)
17276     (lookup *eax *(eax+4))  # => eax
17277     89/<- %edx 0/r32/eax
17278     # out->tag
17279     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
17280     # out->operation
17281     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
17282     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
17283     # out->inouts->value->name
17284     # . eax = out->inouts
17285     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17286     # . eax = out->inouts->value
17287     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17288     # . eax = out->inouts->value->name
17289     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17290     # .
17291     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
17292     # . epilogue
17293     89/<- %esp 5/r32/ebp
17294     5d/pop-to-ebp
17295     c3/return
17296 
17297 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
17298     # . prologue
17299     55/push-ebp
17300     89/<- %ebp 4/r32/esp
17301     # . save registers
17302     50/push-eax
17303     51/push-ecx
17304     # ecx = out
17305     8b/-> *(ebp+0x14) 1/r32/ecx
17306     #
17307     (allocate *(ebp+8) *Var-size %ecx)
17308     # var out-addr/eax: (addr var)
17309     (lookup *ecx *(ecx+4))  # => eax
17310     # out-addr->name = name
17311     8b/-> *(ebp+0xc) 1/r32/ecx
17312     89/<- *eax 1/r32/ecx  # Var-name
17313     8b/-> *(ebp+0x10) 1/r32/ecx
17314     89/<- *(eax+4) 1/r32/ecx  # Var-name
17315 #?     (write-buffered Stderr "var ")
17316 #?     (lookup *(ebp+0xc) *(ebp+0x10))
17317 #?     (write-buffered Stderr %eax)
17318 #?     (write-buffered Stderr " at ")
17319 #?     8b/-> *(ebp+0x14) 1/r32/ecx
17320 #?     (lookup *ecx *(ecx+4))  # => eax
17321 #?     (write-int32-hex-buffered Stderr %eax)
17322 #?     (write-buffered Stderr Newline)
17323 #?     (flush Stderr)
17324 $new-var:end:
17325     # . restore registers
17326     59/pop-to-ecx
17327     58/pop-to-eax
17328     # . epilogue
17329     89/<- %esp 5/r32/ebp
17330     5d/pop-to-ebp
17331     c3/return
17332 
17333 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)
17334     # . prologue
17335     55/push-ebp
17336     89/<- %ebp 4/r32/esp
17337     # . save registers
17338     50/push-eax
17339     51/push-ecx
17340     # if (!is-hex-int?(name)) abort
17341     (is-hex-int? *(ebp+0xc))  # => eax
17342     3d/compare-eax-and 0/imm32/false
17343     0f 84/jump-if-= $new-literal-integer:abort/disp32
17344     # a little more error-checking
17345     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
17346     # out = new var(s)
17347     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
17348     # var out-addr/ecx: (addr var) = lookup(*out)
17349     8b/-> *(ebp+0x10) 0/r32/eax
17350     (lookup *eax *(eax+4))  # => eax
17351     89/<- %ecx 0/r32/eax
17352     # out-addr->block-depth = *Curr-block-depth
17353     8b/-> *Curr-block-depth 0/r32/eax
17354     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
17355     # out-addr->type = new tree()
17356     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
17357     (allocate *(ebp+8) *Type-tree-size %eax)
17358     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17359     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
17360     # nothing else to do; default type is 'literal'
17361 $new-literal-integer:end:
17362     # . reclaim locals
17363     81 0/subop/add %esp 8/imm32
17364     # . restore registers
17365     59/pop-to-ecx
17366     58/pop-to-eax
17367     # . epilogue
17368     89/<- %esp 5/r32/ebp
17369     5d/pop-to-ebp
17370     c3/return
17371 
17372 $new-literal-integer:abort:
17373     (write-buffered *(ebp+0x18) "fn ")
17374     8b/-> *(ebp+0x14) 0/r32/eax
17375     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17376     (write-buffered *(ebp+0x18) %eax)
17377     (write-buffered *(ebp+0x18) ": variable '")
17378     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
17379     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
17380     (flush *(ebp+0x18))
17381     (stop *(ebp+0x1c) 1)
17382     # never gets here
17383 
17384 # precondition: name is a valid hex integer; require a '0x' prefix
17385 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
17386     # . prologue
17387     55/push-ebp
17388     89/<- %ebp 4/r32/esp
17389     # . save registers
17390     50/push-eax
17391     51/push-ecx
17392     52/push-edx
17393     # ecx = name
17394     8b/-> *(ebp+8) 1/r32/ecx
17395     # var start/edx: (addr byte) = name->start
17396     8b/-> *ecx 2/r32/edx
17397     # if (*start == '-') ++start
17398     b8/copy-to-eax 0/imm32
17399     8a/copy-byte *edx 0/r32/AL
17400     3d/compare-eax-and 0x2d/imm32/dash
17401     {
17402       75/jump-if-!= break/disp8
17403       42/increment-edx
17404     }
17405     # var end/ecx: (addr byte) = name->end
17406     8b/-> *(ecx+4) 1/r32/ecx
17407     # var len/eax: int = name->end - name->start
17408     89/<- %eax 1/r32/ecx
17409     29/subtract-from %eax 2/r32/edx
17410     # if (len <= 1) return
17411     3d/compare-eax-with 1/imm32
17412     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
17413 $check-mu-hex-int:length->-1:
17414     # if slice-starts-with?({start, end}, "0x") return
17415     # . var tmp = {start, end}
17416     51/push-ecx
17417     52/push-edx
17418     89/<- %eax 4/r32/esp
17419     # .
17420     (slice-starts-with? %eax "0x")  # => eax
17421     # . reclaim tmp
17422     81 0/subop/add %esp 8/imm32
17423     # .
17424     3d/compare-eax-with 0/imm32/false
17425     75/jump-if-!= $check-mu-hex-int:end/disp8
17426 $check-mu-hex-int:abort:
17427     # otherwise abort
17428     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
17429     (write-slice-buffered *(ebp+0xc) *(ebp+8))
17430     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
17431     (flush *(ebp+0xc))
17432     (stop *(ebp+0x10) 1)
17433 $check-mu-hex-int:end:
17434     # . restore registers
17435     5a/pop-to-edx
17436     59/pop-to-ecx
17437     58/pop-to-eax
17438     # . epilogue
17439     89/<- %esp 5/r32/ebp
17440     5d/pop-to-ebp
17441     c3/return
17442 
17443 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
17444     # . prologue
17445     55/push-ebp
17446     89/<- %ebp 4/r32/esp
17447     # . save registers
17448     50/push-eax
17449     51/push-ecx
17450     # var s/ecx: (handle array byte)
17451     68/push 0/imm32
17452     68/push 0/imm32
17453     89/<- %ecx 4/r32/esp
17454     # s = slice-to-string(name)
17455     (slice-to-string Heap *(ebp+0xc) %ecx)
17456     # allocate to out
17457     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
17458     # var out-addr/ecx: (addr var) = lookup(*out)
17459     8b/-> *(ebp+0x10) 1/r32/ecx
17460     (lookup *ecx *(ecx+4))  # => eax
17461     89/<- %ecx 0/r32/eax
17462     # out-addr->block-depth = *Curr-block-depth
17463     8b/-> *Curr-block-depth 0/r32/eax
17464     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
17465     # out-addr->type/eax = new type
17466     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
17467     (allocate *(ebp+8) *Type-tree-size %eax)
17468     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17469     # nothing else to do; default type is 'literal'
17470     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
17471 $new-literal:end:
17472     # . reclaim locals
17473     81 0/subop/add %esp 8/imm32
17474     # . restore registers
17475     59/pop-to-ecx
17476     58/pop-to-eax
17477     # . epilogue
17478     89/<- %esp 5/r32/ebp
17479     5d/pop-to-ebp
17480     c3/return
17481 
17482 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
17483     # . prologue
17484     55/push-ebp
17485     89/<- %ebp 4/r32/esp
17486     # . save registers
17487     50/push-eax
17488     51/push-ecx
17489     # var s/ecx: (handle array byte)
17490     68/push 0/imm32
17491     68/push 0/imm32
17492     89/<- %ecx 4/r32/esp
17493     # s = slice-to-string(name)
17494     (slice-to-string Heap *(ebp+0xc) %ecx)
17495     # allocate to out
17496     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
17497     # var out-addr/ecx: (addr var) = lookup(*out)
17498     8b/-> *(ebp+0x10) 1/r32/ecx
17499     (lookup *ecx *(ecx+4))  # => eax
17500     89/<- %ecx 0/r32/eax
17501     # out-addr->block-depth = *Curr-block-depth
17502     8b/-> *Curr-block-depth 0/r32/eax
17503     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
17504     # out-addr->type/eax = new type
17505     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
17506     (allocate *(ebp+8) *Type-tree-size %eax)
17507     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17508     # out-addr->type->value = literal-string
17509     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
17510     # out-addr->type->is-atom? = true
17511     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
17512 $new-literal-string:end:
17513     # . reclaim locals
17514     81 0/subop/add %esp 8/imm32
17515     # . restore registers
17516     59/pop-to-ecx
17517     58/pop-to-eax
17518     # . epilogue
17519     89/<- %esp 5/r32/ebp
17520     5d/pop-to-ebp
17521     c3/return
17522 
17523 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
17524     # . prologue
17525     55/push-ebp
17526     89/<- %ebp 4/r32/esp
17527     # . save registers
17528     51/push-ecx
17529     # var tmp/ecx: (handle array byte)
17530     68/push 0/imm32
17531     68/push 0/imm32
17532     89/<- %ecx 4/r32/esp
17533     # tmp = slice-to-string(name)
17534     (slice-to-string Heap *(ebp+0xc) %ecx)
17535     # out = new-var(tmp)
17536     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
17537 $new-var-from-slice:end:
17538     # . reclaim locals
17539     81 0/subop/add %esp 8/imm32
17540     # . restore registers
17541     59/pop-to-ecx
17542     # . epilogue
17543     89/<- %esp 5/r32/ebp
17544     5d/pop-to-ebp
17545     c3/return
17546 
17547 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
17548     # . prologue
17549     55/push-ebp
17550     89/<- %ebp 4/r32/esp
17551     # . save registers
17552     50/push-eax
17553     51/push-ecx
17554     #
17555     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
17556     # var out-addr/eax: (addr stmt) = lookup(*out)
17557     8b/-> *(ebp+0x14) 0/r32/eax
17558     (lookup *eax *(eax+4))  # => eax
17559     # out-addr->tag = stmt
17560     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
17561     # result->var = var
17562     8b/-> *(ebp+0xc) 1/r32/ecx
17563     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
17564     8b/-> *(ebp+0x10) 1/r32/ecx
17565     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
17566 $new-var-def:end:
17567     # . restore registers
17568     59/pop-to-ecx
17569     58/pop-to-eax
17570     # . epilogue
17571     89/<- %esp 5/r32/ebp
17572     5d/pop-to-ebp
17573     c3/return
17574 
17575 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
17576     # . prologue
17577     55/push-ebp
17578     89/<- %ebp 4/r32/esp
17579     # . save registers
17580     50/push-eax
17581     # eax = out
17582     8b/-> *(ebp+0x14) 0/r32/eax
17583     #
17584     (allocate *(ebp+8) *Stmt-size %eax)
17585     # var out-addr/eax: (addr stmt) = lookup(*out)
17586     (lookup *eax *(eax+4))  # => eax
17587     # set tag
17588     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
17589     # set output
17590     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
17591     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
17592 $new-reg-var-def:end:
17593     # . restore registers
17594     58/pop-to-eax
17595     # . epilogue
17596     89/<- %esp 5/r32/ebp
17597     5d/pop-to-ebp
17598     c3/return
17599 
17600 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
17601     # . prologue
17602     55/push-ebp
17603     89/<- %ebp 4/r32/esp
17604     # . save registers
17605     50/push-eax
17606     51/push-ecx
17607     57/push-edi
17608     # edi = out
17609     8b/-> *(ebp+0x1c) 7/r32/edi
17610     # *out = new list
17611     (allocate *(ebp+8) *List-size %edi)
17612     # var out-addr/edi: (addr list _type) = lookup(*out)
17613     (lookup *edi *(edi+4))  # => eax
17614     89/<- %edi 0/r32/eax
17615     # out-addr->value = value
17616     8b/-> *(ebp+0xc) 0/r32/eax
17617     89/<- *edi 0/r32/eax  # List-value
17618     8b/-> *(ebp+0x10) 0/r32/eax
17619     89/<- *(edi+4) 0/r32/eax  # List-value
17620     # if (list == null) return
17621     81 7/subop/compare *(ebp+0x14) 0/imm32
17622     74/jump-if-= $append-list:end/disp8
17623     # otherwise append
17624 $append-list:non-empty-list:
17625     # var curr/eax: (addr list _type) = lookup(list)
17626     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
17627     # while (curr->next != null) curr = curr->next
17628     {
17629       81 7/subop/compare *(eax+8) 0/imm32  # List-next
17630       74/jump-if-= break/disp8
17631       # curr = lookup(curr->next)
17632       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
17633       #
17634       eb/jump loop/disp8
17635     }
17636     # edi = out
17637     8b/-> *(ebp+0x1c) 7/r32/edi
17638     # curr->next = out
17639     8b/-> *edi 1/r32/ecx
17640     89/<- *(eax+8) 1/r32/ecx  # List-next
17641     8b/-> *(edi+4) 1/r32/ecx
17642     89/<- *(eax+0xc) 1/r32/ecx  # List-next
17643     # out = list
17644     8b/-> *(ebp+0x14) 1/r32/ecx
17645     89/<- *edi 1/r32/ecx
17646     8b/-> *(ebp+0x18) 1/r32/ecx
17647     89/<- *(edi+4) 1/r32/ecx
17648 $append-list:end:
17649     # . restore registers
17650     5f/pop-to-edi
17651     59/pop-to-ecx
17652     58/pop-to-eax
17653     # . epilogue
17654     89/<- %esp 5/r32/ebp
17655     5d/pop-to-ebp
17656     c3/return
17657 
17658 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
17659     # . prologue
17660     55/push-ebp
17661     89/<- %ebp 4/r32/esp
17662     # . save registers
17663     50/push-eax
17664     51/push-ecx
17665     57/push-edi
17666     # edi = out
17667     8b/-> *(ebp+0x20) 7/r32/edi
17668     # out = new stmt-var
17669     (allocate *(ebp+8) *Stmt-var-size %edi)
17670     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
17671     (lookup *edi *(edi+4))  # => eax
17672     89/<- %ecx 0/r32/eax
17673     # out-addr->value = v
17674     8b/-> *(ebp+0xc) 0/r32/eax
17675     89/<- *ecx 0/r32/eax  # Stmt-var-value
17676     8b/-> *(ebp+0x10) 0/r32/eax
17677     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
17678     # out-addr->is-deref? = is-deref?
17679     8b/-> *(ebp+0x1c) 0/r32/eax
17680     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
17681     # if (vars == null) return result
17682     81 7/subop/compare *(ebp+0x14) 0/imm32/null
17683     74/jump-if-= $append-stmt-var:end/disp8
17684     # otherwise append
17685     # var curr/eax: (addr stmt-var) = lookup(vars)
17686     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
17687     # while (curr->next != null) curr = curr->next
17688     {
17689       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
17690       74/jump-if-= break/disp8
17691       # curr = lookup(curr->next)
17692       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
17693       #
17694       eb/jump loop/disp8
17695     }
17696     # curr->next = out
17697     8b/-> *edi 1/r32/ecx
17698     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
17699     8b/-> *(edi+4) 1/r32/ecx
17700     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
17701     # out = vars
17702     8b/-> *(ebp+0x14) 1/r32/ecx
17703     89/<- *edi 1/r32/ecx
17704     8b/-> *(ebp+0x18) 1/r32/ecx
17705     89/<- *(edi+4) 1/r32/ecx
17706 $append-stmt-var:end:
17707     # . restore registers
17708     5f/pop-to-edi
17709     59/pop-to-ecx
17710     58/pop-to-eax
17711     # . epilogue
17712     89/<- %esp 5/r32/ebp
17713     5d/pop-to-ebp
17714     c3/return
17715 
17716 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
17717     # . prologue
17718     55/push-ebp
17719     89/<- %ebp 4/r32/esp
17720     # . save registers
17721     50/push-eax
17722     56/push-esi
17723     # esi = block
17724     8b/-> *(ebp+0xc) 6/r32/esi
17725     # block->stmts = append(x, block->stmts)
17726     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
17727     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
17728 $append-to-block:end:
17729     # . restore registers
17730     5e/pop-to-esi
17731     58/pop-to-eax
17732     # . epilogue
17733     89/<- %esp 5/r32/ebp
17734     5d/pop-to-ebp
17735     c3/return
17736 
17737 ## Parsing types
17738 # We need to create metadata on user-defined types, and we need to use this
17739 # metadata as we parse instructions.
17740 # However, we also want to allow types to be used before their definitions.
17741 # This means we can't ever assume any type data structures exist.
17742 
17743 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
17744     # . prologue
17745     55/push-ebp
17746     89/<- %ebp 4/r32/esp
17747     # . save registers
17748     50/push-eax
17749     56/push-esi
17750     # var container-type/esi: type-id
17751     (container-type *(ebp+8))  # => eax
17752     89/<- %esi 0/r32/eax
17753     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
17754     68/push 0/imm32
17755     68/push 0/imm32
17756     89/<- %eax 4/r32/esp
17757     (find-or-create-typeinfo %esi %eax)
17758     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
17759     (lookup *eax *(eax+4))  # => eax
17760     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
17761 #?     (write-buffered Stderr "constant: ")
17762 #?     (write-slice-buffered Stderr *(ebp+0xc))
17763 #?     (write-buffered Stderr Newline)
17764 #?     (flush Stderr)
17765     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
17766 #?     8b/-> *(ebp+0x10) 0/r32/eax
17767 #?     (write-buffered Stderr "@")
17768 #?     (lookup *eax *(eax+4))
17769 #?     (write-int32-hex-buffered Stderr %eax)
17770 #?     (lookup *eax *(eax+4))
17771 #?     (write-buffered Stderr %eax)
17772 #?     (write-buffered Stderr Newline)
17773 #?     (flush Stderr)
17774 #?     (write-buffered Stderr "offset: ")
17775 #?     8b/-> *(eax+0x14) 0/r32/eax
17776 #?     (write-int32-hex-buffered Stderr %eax)
17777 #?     (write-buffered Stderr Newline)
17778 #?     (flush Stderr)
17779 $lookup-or-create-constant:end:
17780     # . reclaim locals
17781     81 0/subop/add %esp 8/imm32
17782     # . restore registers
17783     5e/pop-to-esi
17784     58/pop-to-eax
17785     # . epilogue
17786     89/<- %esp 5/r32/ebp
17787     5d/pop-to-ebp
17788     c3/return
17789 
17790 # if addr var:
17791 #   container->var->type->right->left->value
17792 # otherwise
17793 #   container->var->type->value
17794 container-type:  # container: (addr stmt-var) -> result/eax: type-id
17795     # . prologue
17796     55/push-ebp
17797     89/<- %ebp 4/r32/esp
17798     #
17799     8b/-> *(ebp+8) 0/r32/eax
17800     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17801     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17802     {
17803       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
17804       74/jump-if-= break/disp8
17805       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17806       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17807     }
17808     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
17809 $container-type:end:
17810     # . epilogue
17811     89/<- %esp 5/r32/ebp
17812     5d/pop-to-ebp
17813     c3/return
17814 
17815 is-container?:  # t: type-id -> result/eax: boolean
17816     # . prologue
17817     55/push-ebp
17818     89/<- %ebp 4/r32/esp
17819     #
17820     8b/-> *(ebp+8) 0/r32/eax
17821     c1/shift 4/subop/left %eax 2/imm8
17822     3b/compare 0/r32/eax *Primitive-type-ids
17823     0f 9d/set-if->= %al
17824     81 4/subop/and %eax 0xff/imm32
17825 $is-container?:end:
17826     # . epilogue
17827     89/<- %esp 5/r32/ebp
17828     5d/pop-to-ebp
17829     c3/return
17830 
17831 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
17832     # . prologue
17833     55/push-ebp
17834     89/<- %ebp 4/r32/esp
17835     # . save registers
17836     50/push-eax
17837     51/push-ecx
17838     52/push-edx
17839     57/push-edi
17840     # edi = out
17841     8b/-> *(ebp+0xc) 7/r32/edi
17842     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
17843     68/push 0/imm32
17844     68/push 0/imm32
17845     89/<- %ecx 4/r32/esp
17846     # find-typeinfo(t, out)
17847     (find-typeinfo *(ebp+8) %edi)
17848     {
17849       # if (*out != 0) break
17850       81 7/subop/compare *edi 0/imm32
17851       0f 85/jump-if-!= break/disp32
17852 $find-or-create-typeinfo:create:
17853       # *out = allocate
17854       (allocate Heap *Typeinfo-size %edi)
17855       # var tmp/eax: (addr typeinfo) = lookup(*out)
17856       (lookup *edi *(edi+4))  # => eax
17857 #?     (write-buffered Stderr "created typeinfo at ")
17858 #?     (write-int32-hex-buffered Stderr %eax)
17859 #?     (write-buffered Stderr " for type-id ")
17860 #?     (write-int32-hex-buffered Stderr *(ebp+8))
17861 #?     (write-buffered Stderr Newline)
17862 #?     (flush Stderr)
17863       # tmp->id = t
17864       8b/-> *(ebp+8) 2/r32/edx
17865       89/<- *eax 2/r32/edx  # Typeinfo-id
17866       # tmp->fields = new table
17867       # . fields = new table
17868       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
17869       # . tmp->fields = fields
17870       8b/-> *ecx 2/r32/edx
17871       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
17872       8b/-> *(ecx+4) 2/r32/edx
17873       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
17874       # tmp->next = Program->types
17875       8b/-> *_Program-types 1/r32/ecx
17876       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
17877       8b/-> *_Program-types->payload 1/r32/ecx
17878       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
17879       # Program->types = out
17880       8b/-> *edi 1/r32/ecx
17881       89/<- *_Program-types 1/r32/ecx
17882       8b/-> *(edi+4) 1/r32/ecx
17883       89/<- *_Program-types->payload 1/r32/ecx
17884     }
17885 $find-or-create-typeinfo:end:
17886     # . reclaim locals
17887     81 0/subop/add %esp 8/imm32
17888     # . restore registers
17889     5f/pop-to-edi
17890     5a/pop-to-edx
17891     59/pop-to-ecx
17892     58/pop-to-eax
17893     # . epilogue
17894     89/<- %esp 5/r32/ebp
17895     5d/pop-to-ebp
17896     c3/return
17897 
17898 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
17899     # . prologue
17900     55/push-ebp
17901     89/<- %ebp 4/r32/esp
17902     # . save registers
17903     50/push-eax
17904     51/push-ecx
17905     52/push-edx
17906     57/push-edi
17907     # ecx = t
17908     8b/-> *(ebp+8) 1/r32/ecx
17909     # edi = out
17910     8b/-> *(ebp+0xc) 7/r32/edi
17911     # *out = Program->types
17912     8b/-> *_Program-types 0/r32/eax
17913     89/<- *edi 0/r32/eax
17914     8b/-> *_Program-types->payload 0/r32/eax
17915     89/<- *(edi+4) 0/r32/eax
17916     {
17917 $find-typeinfo:loop:
17918       # if (*out == 0) break
17919       81 7/subop/compare *edi 0/imm32
17920       74/jump-if-= break/disp8
17921 $find-typeinfo:check:
17922       # var tmp/eax: (addr typeinfo) = lookup(*out)
17923       (lookup *edi *(edi+4))  # => eax
17924       # if (tmp->id == t) break
17925       39/compare *eax 1/r32/ecx  # Typeinfo-id
17926       74/jump-if-= break/disp8
17927 $find-typeinfo:continue:
17928       # *out = tmp->next
17929       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
17930       89/<- *edi 2/r32/edx
17931       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
17932       89/<- *(edi+4) 2/r32/edx
17933       #
17934       eb/jump loop/disp8
17935     }
17936 $find-typeinfo:end:
17937     # . restore registers
17938     5f/pop-to-edi
17939     5a/pop-to-edx
17940     59/pop-to-ecx
17941     58/pop-to-eax
17942     # . epilogue
17943     89/<- %esp 5/r32/ebp
17944     5d/pop-to-ebp
17945     c3/return
17946 
17947 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
17948     # . prologue
17949     55/push-ebp
17950     89/<- %ebp 4/r32/esp
17951     # . save registers
17952     50/push-eax
17953     52/push-edx
17954     57/push-edi
17955     # var dest/edi: (handle typeinfo-entry)
17956     68/push 0/imm32
17957     68/push 0/imm32
17958     89/<- %edi 4/r32/esp
17959     # find-or-create-typeinfo-fields(T, f, dest)
17960     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
17961     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
17962     (lookup *edi *(edi+4))  # => eax
17963     89/<- %edi 0/r32/eax
17964     # if dest-addr->output-var doesn't exist, create it
17965     {
17966       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
17967       0f 85/jump-if-!= break/disp32
17968       # dest-addr->output-var = new var(dummy name, type, -1 offset)
17969       # . var name/eax: (handle array byte) = "field"
17970       68/push 0/imm32
17971       68/push 0/imm32
17972       89/<- %eax 4/r32/esp
17973       (slice-to-string Heap *(ebp+0xc) %eax)
17974       # . new var
17975       8d/copy-address *(edi+0xc) 2/r32/edx
17976       (new-var Heap  *eax *(eax+4)  %edx)
17977       # . reclaim name
17978       81 0/subop/add %esp 8/imm32
17979       # var result/edx: (addr var) = lookup(dest-addr->output-var)
17980       (lookup *(edi+0xc) *(edi+0x10))  # => eax
17981       89/<- %edx 0/r32/eax
17982       # result->type = new constant type
17983       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
17984       (allocate Heap *Type-tree-size %eax)
17985       (lookup *(edx+8) *(edx+0xc))  # => eax
17986       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
17987       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
17988       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
17989       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
17990       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
17991       # result->offset isn't filled out yet
17992       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
17993     }
17994     # out = dest-addr->output-var
17995     8b/-> *(ebp+0x10) 2/r32/edx
17996     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
17997     89/<- *edx 0/r32/eax
17998     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
17999     89/<- *(edx+4) 0/r32/eax
18000 $find-or-create-typeinfo-output-var:end:
18001     # . reclaim locals
18002     81 0/subop/add %esp 8/imm32
18003     # . restore registers
18004     5f/pop-to-edi
18005     5a/pop-to-edx
18006     58/pop-to-eax
18007     # . epilogue
18008     89/<- %esp 5/r32/ebp
18009     5d/pop-to-ebp
18010     c3/return
18011 
18012 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
18013     # . prologue
18014     55/push-ebp
18015     89/<- %ebp 4/r32/esp
18016     # . save registers
18017     50/push-eax
18018     56/push-esi
18019     57/push-edi
18020     # eax = lookup(T->fields)
18021     8b/-> *(ebp+8) 0/r32/eax
18022     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
18023     # edi = out
18024     8b/-> *(ebp+0x10) 7/r32/edi
18025     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
18026     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
18027     89/<- %esi 0/r32/eax
18028     # if src doesn't exist, allocate it
18029     {
18030       81 7/subop/compare *esi 0/imm32
18031       75/jump-if-!= break/disp8
18032       (allocate Heap *Typeinfo-entry-size %esi)
18033 #?       (write-buffered Stderr "handle at ")
18034 #?       (write-int32-hex-buffered Stderr %esi)
18035 #?       (write-buffered Stderr ": ")
18036 #?       (write-int32-hex-buffered Stderr *esi)
18037 #?       (write-buffered Stderr " ")
18038 #?       (write-int32-hex-buffered Stderr *(esi+4))
18039 #?       (write-buffered Stderr Newline)
18040 #?       (flush Stderr)
18041 #?       (lookup *esi *(esi+4))
18042 #?       (write-buffered Stderr "created typeinfo fields at ")
18043 #?       (write-int32-hex-buffered Stderr %esi)
18044 #?       (write-buffered Stderr " for ")
18045 #?       (write-int32-hex-buffered Stderr *(ebp+8))
18046 #?       (write-buffered Stderr Newline)
18047 #?       (flush Stderr)
18048     }
18049     # *out = src
18050     # . *edi = *src
18051     8b/-> *esi 0/r32/eax
18052     89/<- *edi 0/r32/eax
18053     8b/-> *(esi+4) 0/r32/eax
18054     89/<- *(edi+4) 0/r32/eax
18055 $find-or-create-typeinfo-fields:end:
18056     # . restore registers
18057     5f/pop-to-edi
18058     5e/pop-to-esi
18059     58/pop-to-eax
18060     # . epilogue
18061     89/<- %esp 5/r32/ebp
18062     5d/pop-to-ebp
18063     c3/return
18064 
18065 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
18066     # pseudocode:
18067     #   var line: (stream byte 512)
18068     #   curr-index = 0
18069     #   while true
18070     #     clear-stream(line)
18071     #     read-line-buffered(in, line)
18072     #     if line->write == 0
18073     #       abort
18074     #     word-slice = next-mu-token(line)
18075     #     if slice-empty?(word-slice)               # end of line
18076     #       continue
18077     #     if slice-equal?(word-slice, "}")
18078     #       break
18079     #     var v: (handle var) = parse-var-with-type(word-slice, line)
18080     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
18081     #     TODO: ensure that r->first is null
18082     #     r->index = curr-index
18083     #     curr-index++
18084     #     r->input-var = v
18085     #     if r->output-var == 0
18086     #       r->output-var = new literal
18087     #     TODO: ensure nothing else in line
18088     # t->total-size-in-bytes = -2 (not yet initialized)
18089     #
18090     # . prologue
18091     55/push-ebp
18092     89/<- %ebp 4/r32/esp
18093     # var curr-index: int at *(ebp-4)
18094     68/push 0/imm32
18095     # . save registers
18096     50/push-eax
18097     51/push-ecx
18098     52/push-edx
18099     53/push-ebx
18100     56/push-esi
18101     57/push-edi
18102     # edi = t
18103     8b/-> *(ebp+0xc) 7/r32/edi
18104     # var line/ecx: (stream byte 512)
18105     81 5/subop/subtract %esp 0x200/imm32
18106     68/push 0x200/imm32/size
18107     68/push 0/imm32/read
18108     68/push 0/imm32/write
18109     89/<- %ecx 4/r32/esp
18110     # var word-slice/edx: slice
18111     68/push 0/imm32/end
18112     68/push 0/imm32/start
18113     89/<- %edx 4/r32/esp
18114     # var v/esi: (handle var)
18115     68/push 0/imm32
18116     68/push 0/imm32
18117     89/<- %esi 4/r32/esp
18118     # var r/ebx: (handle typeinfo-entry)
18119     68/push 0/imm32
18120     68/push 0/imm32
18121     89/<- %ebx 4/r32/esp
18122     {
18123 $populate-mu-type:line-loop:
18124       (clear-stream %ecx)
18125       (read-line-buffered *(ebp+8) %ecx)
18126       # if (line->write == 0) abort
18127       81 7/subop/compare *ecx 0/imm32
18128       0f 84/jump-if-= $populate-mu-type:error1/disp32
18129 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18135       (next-mu-token %ecx %edx)
18136       # if slice-empty?(word-slice) continue
18137       (slice-empty? %edx)  # => eax
18138       3d/compare-eax-and 0/imm32
18139       0f 85/jump-if-!= loop/disp32
18140       # if slice-equal?(word-slice, "}") break
18141       (slice-equal? %edx "}")
18142       3d/compare-eax-and 0/imm32
18143       0f 85/jump-if-!= break/disp32
18144 $populate-mu-type:parse-element:
18145       # v = parse-var-with-type(word-slice, first-line)
18146       # must do this first to strip the trailing ':' from word-slice before
18147       # using it in find-or-create-typeinfo-fields below
18148       # TODO: clean up that mutation in parse-var-with-type
18149       (parse-var-with-type %edx %ecx %esi *(ebp+0x10) *(ebp+0x14))
18150       # if v is an addr, abort
18151       (lookup *esi *(esi+4))  # => eax
18152       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18153       (is-mu-addr-type? %eax)  # => eax
18154       3d/compare-eax-and 0/imm32/false
18155       0f 85/jump-if-!= $populate-mu-type:error2/disp32
18156       # if v is an array, abort  (we could support it, but initialization gets complex)
18157       (lookup *esi *(esi+4))  # => eax
18158       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18159       (is-mu-array-type? %eax)  # => eax
18160       3d/compare-eax-and 0/imm32/false
18161       0f 85/jump-if-!= $populate-mu-type:error3/disp32
18162       # if v is a byte, abort
18163       (lookup *esi *(esi+4))  # => eax
18164       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18165       (is-simple-mu-type? %eax 8)  # byte => eax
18166       3d/compare-eax-and 0/imm32/false
18167       0f 85/jump-if-!= $populate-mu-type:error4/disp32
18168       # if v is a slice, abort
18169       (lookup *esi *(esi+4))  # => eax
18170       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18171       (is-simple-mu-type? %eax 0xc)  # slice => eax
18172       3d/compare-eax-and 0/imm32/false
18173       0f 85/jump-if-!= $populate-mu-type:error5/disp32
18174       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
18175       (lookup *esi *(esi+4))  # => eax
18176       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18177       (is-mu-stream-type? %eax)  # => eax
18178       3d/compare-eax-and 0/imm32/false
18179       0f 85/jump-if-!= $populate-mu-type:error6/disp32
18180       # var tmp/ecx
18181       51/push-ecx
18182 $populate-mu-type:create-typeinfo-fields:
18183       # var r/ebx: (handle typeinfo-entry)
18184       (find-or-create-typeinfo-fields %edi %edx %ebx)
18185       # r->index = curr-index
18186       (lookup *ebx *(ebx+4))  # => eax
18187       8b/-> *(ebp-4) 1/r32/ecx
18188 #?       (write-buffered Stderr "saving index ")
18189 #?       (write-int32-hex-buffered Stderr %ecx)
18190 #?       (write-buffered Stderr " at ")
18191 #?       (write-int32-hex-buffered Stderr %edi)
18192 #?       (write-buffered Stderr Newline)
18193 #?       (flush Stderr)
18194       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
18195       # ++curr-index
18196       ff 0/subop/increment *(ebp-4)
18197 $populate-mu-type:set-input-type:
18198       # r->input-var = v
18199       8b/-> *esi 1/r32/ecx
18200       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
18201       8b/-> *(esi+4) 1/r32/ecx
18202       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
18203       # restore line
18204       59/pop-to-ecx
18205       {
18206 $populate-mu-type:create-output-type:
18207         # if (r->output-var == 0) create a new var with some placeholder data
18208         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
18209         75/jump-if-!= break/disp8
18210         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
18211         (new-literal Heap %edx %eax)
18212       }
18213       e9/jump loop/disp32
18214     }
18215 $populate-mu-type:invalidate-total-size-in-bytes:
18216     # Offsets and total size may not be accurate here since we may not yet
18217     # have encountered the element types.
18218     # We'll recompute them separately after parsing the entire program.
18219     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
18220 $populate-mu-type:end:
18221     # . reclaim locals
18222     81 0/subop/add %esp 0x224/imm32
18223     # . restore registers
18224     5f/pop-to-edi
18225     5e/pop-to-esi
18226     5b/pop-to-ebx
18227     5a/pop-to-edx
18228     59/pop-to-ecx
18229     58/pop-to-eax
18230     # reclaim curr-index
18231     81 0/subop/add %esp 4/imm32
18232     # . epilogue
18233     89/<- %esp 5/r32/ebp
18234     5d/pop-to-ebp
18235     c3/return
18236 
18237 $populate-mu-type:error1:
18238     # error("incomplete type definition '" t->name "'\n")
18239     (write-buffered *(ebp+0x10) "incomplete type definition '")
18240     (type-name *edi)  # Typeinfo-id => eax
18241     (write-buffered *(ebp+0x10) %eax)
18242     (write-buffered *(ebp+0x10) "\n")
18243     (flush *(ebp+0x10))
18244     (stop *(ebp+0x14) 1)
18245     # never gets here
18246 
18247 $populate-mu-type:error2:
18248     (write-buffered *(ebp+0x10) "type ")
18249     (type-name *edi)  # Typeinfo-id => eax
18250     (write-buffered *(ebp+0x10) %eax)
18251     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
18252     (flush *(ebp+0x10))
18253     (stop *(ebp+0x14) 1)
18254     # never gets here
18255 
18256 $populate-mu-type:error3:
18257     (write-buffered *(ebp+0x10) "type ")
18258     (type-name *edi)  # Typeinfo-id => eax
18259     (write-buffered *(ebp+0x10) %eax)
18260     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
18261     (flush *(ebp+0x10))
18262     (stop *(ebp+0x14) 1)
18263     # never gets here
18264 
18265 $populate-mu-type:error4:
18266     (write-buffered *(ebp+0x10) "type ")
18267     (type-name *edi)  # Typeinfo-id => eax
18268     (write-buffered *(ebp+0x10) %eax)
18269     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
18270     (flush *(ebp+0x10))
18271     (stop *(ebp+0x14) 1)
18272     # never gets here
18273 
18274 $populate-mu-type:error5:
18275     (write-buffered *(ebp+0x10) "type ")
18276     (type-name *edi)  # Typeinfo-id => eax
18277     (write-buffered *(ebp+0x10) %eax)
18278     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
18279     (flush *(ebp+0x10))
18280     (stop *(ebp+0x14) 1)
18281     # never gets here
18282 
18283 $populate-mu-type:error6:
18284     (write-buffered *(ebp+0x10) "type ")
18285     (type-name *edi)  # Typeinfo-id => eax
18286     (write-buffered *(ebp+0x10) %eax)
18287     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
18288     (flush *(ebp+0x10))
18289     (stop *(ebp+0x14) 1)
18290     # never gets here
18291 
18292 type-name:  # index: int -> result/eax: (addr array byte)
18293     # . prologue
18294     55/push-ebp
18295     89/<- %ebp 4/r32/esp
18296     #
18297     (index Type-id *(ebp+8))
18298 $type-name:end:
18299     # . epilogue
18300     89/<- %esp 5/r32/ebp
18301     5d/pop-to-ebp
18302     c3/return
18303 
18304 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
18305     # . prologue
18306     55/push-ebp
18307     89/<- %ebp 4/r32/esp
18308     # . save registers
18309     56/push-esi
18310     # TODO: bounds-check index
18311     # esi = arr
18312     8b/-> *(ebp+8) 6/r32/esi
18313     # eax = index
18314     8b/-> *(ebp+0xc) 0/r32/eax
18315     # eax = *(arr + 12 + index)
18316     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
18317 $index:end:
18318     # . restore registers
18319     5e/pop-to-esi
18320     # . epilogue
18321     89/<- %esp 5/r32/ebp
18322     5d/pop-to-ebp
18323     c3/return
18324 
18325 #######################################################
18326 # Compute type sizes
18327 #######################################################
18328 
18329 # Compute the sizes of all user-defined types.
18330 # We'll need the sizes of their elements, which may be other user-defined
18331 # types, which we will compute as needed.
18332 
18333 # Initially, all user-defined types have their sizes set to -2 (invalid)
18334 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
18335     # . prologue
18336     55/push-ebp
18337     89/<- %ebp 4/r32/esp
18338 $populate-mu-type-sizes:total-sizes:
18339     # var curr/eax: (addr typeinfo) = lookup(Program->types)
18340     (lookup *_Program-types *_Program-types->payload)  # => eax
18341     {
18342       # if (curr == null) break
18343       3d/compare-eax-and 0/imm32/null
18344       74/jump-if-= break/disp8
18345       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
18346       # curr = lookup(curr->next)
18347       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
18348       eb/jump loop/disp8
18349     }
18350 $populate-mu-type-sizes:offsets:
18351     # curr = *Program->types
18352     (lookup *_Program-types *_Program-types->payload)  # => eax
18353     {
18354       # if (curr == null) break
18355       3d/compare-eax-and 0/imm32/null
18356       74/jump-if-= break/disp8
18357       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
18358       # curr = curr->next
18359       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
18360       eb/jump loop/disp8
18361     }
18362 $populate-mu-type-sizes:end:
18363     # . epilogue
18364     89/<- %esp 5/r32/ebp
18365     5d/pop-to-ebp
18366     c3/return
18367 
18368 # compute sizes of all fields, recursing as necessary
18369 # sum up all their sizes to arrive at total size
18370 # fields may be out of order, but that doesn't affect the answer
18371 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
18372     # . prologue
18373     55/push-ebp
18374     89/<- %ebp 4/r32/esp
18375     # . save registers
18376     50/push-eax
18377     51/push-ecx
18378     52/push-edx
18379     56/push-esi
18380     57/push-edi
18381     # esi = T
18382     8b/-> *(ebp+8) 6/r32/esi
18383     # if T is already computed, return
18384     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
18385     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
18386     # if T is being computed, abort
18387     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
18388     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
18389     # tag T (-2 to -1) to avoid infinite recursion
18390     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
18391     # var total-size/edi: int = 0
18392     bf/copy-to-edi 0/imm32
18393     # - for every field, if it's a user-defined type, compute its size
18394     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
18395     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
18396     89/<- %ecx 0/r32/eax
18397     # var table-size/edx: int = table->write
18398     8b/-> *ecx 2/r32/edx  # stream-write
18399     # var curr/ecx: (addr table_row) = table->data
18400     8d/copy-address *(ecx+0xc) 1/r32/ecx
18401     # var max/edx: (addr table_row) = table->data + table->write
18402     8d/copy-address *(ecx+edx) 2/r32/edx
18403     {
18404 $populate-mu-type-sizes-in-type:loop:
18405       # if (curr >= max) break
18406       39/compare %ecx 2/r32/edx
18407       73/jump-if-addr>= break/disp8
18408       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
18409       (lookup *(ecx+8) *(ecx+0xc))  # => eax
18410       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
18411       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
18412       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
18413       # compute size of t->input-var
18414       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
18415       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
18416       # result += eax
18417       01/add-to %edi 0/r32/eax
18418       # curr += row-size
18419       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
18420       #
18421       eb/jump loop/disp8
18422     }
18423     # - save result
18424     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
18425 $populate-mu-type-sizes-in-type:end:
18426     # . restore registers
18427     5f/pop-to-edi
18428     5e/pop-to-esi
18429     5a/pop-to-edx
18430     59/pop-to-ecx
18431     58/pop-to-eax
18432     # . epilogue
18433     89/<- %esp 5/r32/ebp
18434     5d/pop-to-ebp
18435     c3/return
18436 
18437 $populate-mu-type-sizes-in-type:abort:
18438     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
18439     (flush *(ebp+0xc))
18440     (stop *(ebp+0x10) 1)
18441     # never gets here
18442 
18443 # Analogous to size-of, except we need to compute what size-of can just read
18444 # off the right data structures.
18445 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
18446     # . prologue
18447     55/push-ebp
18448     89/<- %ebp 4/r32/esp
18449     # . push registers
18450     51/push-ecx
18451     # var t/ecx: (addr type-tree) = lookup(v->type)
18452     8b/-> *(ebp+8) 1/r32/ecx
18453     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18454     89/<- %ecx 0/r32/eax
18455     # if (t->is-atom == false) t = lookup(t->left)
18456     {
18457       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18458       75/jump-if-!= break/disp8
18459       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18460       89/<- %ecx 0/r32/eax
18461     }
18462     # TODO: ensure t is an atom
18463     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
18464 $compute-size-of-var:end:
18465     # . restore registers
18466     59/pop-to-ecx
18467     # . epilogue
18468     89/<- %esp 5/r32/ebp
18469     5d/pop-to-ebp
18470     c3/return
18471 
18472 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
18473     # . prologue
18474     55/push-ebp
18475     89/<- %ebp 4/r32/esp
18476     # . save registers
18477     51/push-ecx
18478     # var out/ecx: (handle typeinfo)
18479     68/push 0/imm32
18480     68/push 0/imm32
18481     89/<- %ecx 4/r32/esp
18482     # eax = t
18483     8b/-> *(ebp+8) 0/r32/eax
18484     # if t is a literal, return 0
18485     3d/compare-eax-and 0/imm32/literal
18486     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
18487     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
18488     3d/compare-eax-and 8/imm32/byte
18489     {
18490       75/jump-if-!= break/disp8
18491       b8/copy-to-eax 4/imm32
18492       eb/jump $compute-size-of-type-id:end/disp8
18493     }
18494     # if t is a handle, return 8
18495     3d/compare-eax-and 4/imm32/handle
18496     {
18497       75/jump-if-!= break/disp8
18498       b8/copy-to-eax 8/imm32
18499       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
18500     }
18501     # if t is a slice, return 8
18502     3d/compare-eax-and 0xc/imm32/slice
18503     {
18504       75/jump-if-!= break/disp8
18505       b8/copy-to-eax 8/imm32
18506       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
18507     }
18508     # if t is a user-defined type, compute its size
18509     # TODO: support non-atom type
18510     (find-typeinfo %eax %ecx)
18511     {
18512       81 7/subop/compare *ecx 0/imm32
18513       74/jump-if-= break/disp8
18514 $compute-size-of-type-id:user-defined:
18515       (lookup *ecx *(ecx+4))  # => eax
18516       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
18517       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
18518       eb/jump $compute-size-of-type-id:end/disp8
18519     }
18520     # otherwise return the word size
18521     b8/copy-to-eax 4/imm32
18522 $compute-size-of-type-id:end:
18523     # . reclaim locals
18524     81 0/subop/add %esp 8/imm32
18525     # . restore registers
18526     59/pop-to-ecx
18527     # . epilogue
18528     89/<- %esp 5/r32/ebp
18529     5d/pop-to-ebp
18530     c3/return
18531 
18532 # at this point we have total sizes for all user-defined types
18533 # compute offsets for each element
18534 # complication: fields may be out of order
18535 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
18536     # . prologue
18537     55/push-ebp
18538     89/<- %ebp 4/r32/esp
18539     # . save registers
18540     50/push-eax
18541     51/push-ecx
18542     52/push-edx
18543     53/push-ebx
18544     56/push-esi
18545     57/push-edi
18546 #?     (dump-typeinfos "aaa\n")
18547     # var curr-offset/edi: int = 0
18548     bf/copy-to-edi 0/imm32
18549     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
18550     8b/-> *(ebp+8) 1/r32/ecx
18551     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
18552     89/<- %ecx 0/r32/eax
18553     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
18554     8b/-> *ecx 2/r32/edx  # stream-write
18555     c1 5/subop/shift-right-logical  %edx 4/imm8
18556     # var i/ebx: int = 0
18557     bb/copy-to-ebx 0/imm32
18558     {
18559 $populate-mu-type-offsets:loop:
18560       39/compare %ebx 2/r32/edx
18561       0f 8d/jump-if->= break/disp32
18562 #?       (write-buffered Stderr "looking up index ")
18563 #?       (write-int32-hex-buffered Stderr %ebx)
18564 #?       (write-buffered Stderr " in ")
18565 #?       (write-int32-hex-buffered Stderr *(ebp+8))
18566 #?       (write-buffered Stderr Newline)
18567 #?       (flush Stderr)
18568       # var v/esi: (addr typeinfo-entry)
18569       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
18570       89/<- %esi 0/r32/eax
18571       # if v is null, silently move on; we'll emit a nice error message while type-checking
18572       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
18573       74/jump-if-= $populate-mu-type-offsets:end/disp8
18574       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
18575       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
18576       74/jump-if-= $populate-mu-type-offsets:end/disp8
18577       # v->output-var->offset = curr-offset
18578       # . eax: (addr var)
18579       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
18580       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
18581       # curr-offset += size-of(v->input-var)
18582       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
18583       (size-of %eax)  # => eax
18584       01/add-to %edi 0/r32/eax
18585       # ++i
18586       43/increment-ebx
18587       e9/jump loop/disp32
18588     }
18589 $populate-mu-type-offsets:end:
18590     # . restore registers
18591     5f/pop-to-edi
18592     5e/pop-to-esi
18593     5b/pop-to-ebx
18594     5a/pop-to-edx
18595     59/pop-to-ecx
18596     58/pop-to-eax
18597     # . epilogue
18598     89/<- %esp 5/r32/ebp
18599     5d/pop-to-ebp
18600     c3/return
18601 
18602 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)
18603     # . prologue
18604     55/push-ebp
18605     89/<- %ebp 4/r32/esp
18606     # . save registers
18607     51/push-ecx
18608     52/push-edx
18609     53/push-ebx
18610     56/push-esi
18611     57/push-edi
18612     # esi = table
18613     8b/-> *(ebp+8) 6/r32/esi
18614     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
18615     8d/copy-address *(esi+0xc) 1/r32/ecx
18616     # var max/edx: (addr byte) = &table->data[table->write]
18617     8b/-> *esi 2/r32/edx
18618     8d/copy-address *(ecx+edx) 2/r32/edx
18619     {
18620 $locate-typeinfo-entry-with-index:loop:
18621       39/compare %ecx 2/r32/edx
18622       73/jump-if-addr>= break/disp8
18623       # var v/eax: (addr typeinfo-entry)
18624       (lookup *(ecx+8) *(ecx+0xc))  # => eax
18625       # if (v->index == idx) return v
18626       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
18627 #?       (write-buffered Stderr "comparing ")
18628 #?       (write-int32-hex-buffered Stderr %ebx)
18629 #?       (write-buffered Stderr " and ")
18630 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
18631 #?       (write-buffered Stderr Newline)
18632 #?       (flush Stderr)
18633       39/compare *(ebp+0xc) 3/r32/ebx
18634       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
18635       # curr += Typeinfo-entry-size
18636       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
18637       #
18638       eb/jump loop/disp8
18639     }
18640     # return 0
18641     b8/copy-to-eax 0/imm32
18642 $locate-typeinfo-entry-with-index:end:
18643 #?     (write-buffered Stderr "returning ")
18644 #?     (write-int32-hex-buffered Stderr %eax)
18645 #?     (write-buffered Stderr Newline)
18646 #?     (flush Stderr)
18647     # . restore registers
18648     5f/pop-to-edi
18649     5e/pop-to-esi
18650     5b/pop-to-ebx
18651     5a/pop-to-edx
18652     59/pop-to-ecx
18653     # . epilogue
18654     89/<- %esp 5/r32/ebp
18655     5d/pop-to-ebp
18656     c3/return
18657 
18658 dump-typeinfos:  # hdr: (addr array byte)
18659     # . prologue
18660     55/push-ebp
18661     89/<- %ebp 4/r32/esp
18662     # . save registers
18663     50/push-eax
18664     #
18665     (write-buffered Stderr *(ebp+8))
18666     (flush Stderr)
18667     # var curr/eax: (addr typeinfo) = lookup(Program->types)
18668     (lookup *_Program-types *_Program-types->payload)  # => eax
18669     {
18670       # if (curr == null) break
18671       3d/compare-eax-and 0/imm32
18672       74/jump-if-= break/disp8
18673       (write-buffered Stderr "---\n")
18674       (flush Stderr)
18675       (dump-typeinfo %eax)
18676       # curr = lookup(curr->next)
18677       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
18678       eb/jump loop/disp8
18679     }
18680 $dump-typeinfos:end:
18681     # . restore registers
18682     58/pop-to-eax
18683     # . epilogue
18684     89/<- %esp 5/r32/ebp
18685     5d/pop-to-ebp
18686     c3/return
18687 
18688 dump-typeinfo:  # in: (addr typeinfo)
18689     # . prologue
18690     55/push-ebp
18691     89/<- %ebp 4/r32/esp
18692     # . save registers
18693     50/push-eax
18694     51/push-ecx
18695     52/push-edx
18696     53/push-ebx
18697     56/push-esi
18698     57/push-edi
18699     # esi = in
18700     8b/-> *(ebp+8) 6/r32/esi
18701     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
18702     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
18703     89/<- %ecx 0/r32/eax
18704     (write-buffered Stderr "id:")
18705     (write-int32-hex-buffered Stderr *esi)
18706     (write-buffered Stderr "\n")
18707     (write-buffered Stderr "fields @ ")
18708     (write-int32-hex-buffered Stderr %ecx)
18709     (write-buffered Stderr Newline)
18710     (flush Stderr)
18711     (write-buffered Stderr "  write: ")
18712     (write-int32-hex-buffered Stderr *ecx)
18713     (write-buffered Stderr Newline)
18714     (flush Stderr)
18715     (write-buffered Stderr "  read: ")
18716     (write-int32-hex-buffered Stderr *(ecx+4))
18717     (write-buffered Stderr Newline)
18718     (flush Stderr)
18719     (write-buffered Stderr "  size: ")
18720     (write-int32-hex-buffered Stderr *(ecx+8))
18721     (write-buffered Stderr Newline)
18722     (flush Stderr)
18723     # var table-size/edx: int = table->write
18724     8b/-> *ecx 2/r32/edx  # stream-write
18725     # var curr/ecx: (addr table_row) = table->data
18726     8d/copy-address *(ecx+0xc) 1/r32/ecx
18727     # var max/edx: (addr table_row) = table->data + table->write
18728     8d/copy-address *(ecx+edx) 2/r32/edx
18729     {
18730 $dump-typeinfo:loop:
18731       # if (curr >= max) break
18732       39/compare %ecx 2/r32/edx
18733       0f 83/jump-if-addr>= break/disp32
18734       (write-buffered Stderr "  row:\n")
18735       (write-buffered Stderr "    key: ")
18736       (write-int32-hex-buffered Stderr *ecx)
18737       (write-buffered Stderr ",")
18738       (write-int32-hex-buffered Stderr *(ecx+4))
18739       (write-buffered Stderr " = '")
18740       (lookup *ecx *(ecx+4))
18741       (write-buffered Stderr %eax)
18742       (write-buffered Stderr "' @ ")
18743       (write-int32-hex-buffered Stderr %eax)
18744       (write-buffered Stderr Newline)
18745       (flush Stderr)
18746       (write-buffered Stderr "    value: ")
18747       (write-int32-hex-buffered Stderr *(ecx+8))
18748       (write-buffered Stderr ",")
18749       (write-int32-hex-buffered Stderr *(ecx+0xc))
18750       (write-buffered Stderr " = typeinfo-entry@")
18751       (lookup *(ecx+8) *(ecx+0xc))
18752       (write-int32-hex-buffered Stderr %eax)
18753       (write-buffered Stderr Newline)
18754       (flush Stderr)
18755       (write-buffered Stderr "        input var@")
18756       (dump-var 5 %eax)
18757       (lookup *(ecx+8) *(ecx+0xc))
18758       (write-buffered Stderr "        index: ")
18759       (write-int32-hex-buffered Stderr *(eax+8))
18760       (write-buffered Stderr Newline)
18761       (flush Stderr)
18762       (write-buffered Stderr "        output var@")
18763       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
18764       (dump-var 5 %eax)
18765       (flush Stderr)
18766       # curr += row-size
18767       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
18768       #
18769       e9/jump loop/disp32
18770     }
18771 $dump-typeinfo:end:
18772     # . restore registers
18773     5f/pop-to-edi
18774     5e/pop-to-esi
18775     5b/pop-to-ebx
18776     5a/pop-to-edx
18777     59/pop-to-ecx
18778     58/pop-to-eax
18779     # . epilogue
18780     89/<- %esp 5/r32/ebp
18781     5d/pop-to-ebp
18782     c3/return
18783 
18784 dump-var:  # indent: int, v: (addr handle var)
18785     # . prologue
18786     55/push-ebp
18787     89/<- %ebp 4/r32/esp
18788     # . save registers
18789     50/push-eax
18790     53/push-ebx
18791     # eax = v
18792     8b/-> *(ebp+0xc) 0/r32/eax
18793     #
18794     (write-int32-hex-buffered Stderr *eax)
18795     (write-buffered Stderr ",")
18796     (write-int32-hex-buffered Stderr *(eax+4))
18797     (write-buffered Stderr "->")
18798     (lookup *eax *(eax+4))
18799     (write-int32-hex-buffered Stderr %eax)
18800     (write-buffered Stderr Newline)
18801     (flush Stderr)
18802     {
18803       3d/compare-eax-and 0/imm32
18804       0f 84/jump-if-= break/disp32
18805       (emit-indent Stderr *(ebp+8))
18806       (write-buffered Stderr "name: ")
18807       89/<- %ebx 0/r32/eax
18808       (write-int32-hex-buffered Stderr *ebx)  # Var-name
18809       (write-buffered Stderr ",")
18810       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
18811       (write-buffered Stderr "->")
18812       (lookup *ebx *(ebx+4))  # Var-name
18813       (write-int32-hex-buffered Stderr %eax)
18814       {
18815         3d/compare-eax-and 0/imm32
18816         74/jump-if-= break/disp8
18817         (write-buffered Stderr Space)
18818         (write-buffered Stderr %eax)
18819       }
18820       (write-buffered Stderr Newline)
18821       (flush Stderr)
18822       (emit-indent Stderr *(ebp+8))
18823       (write-buffered Stderr "block depth: ")
18824       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
18825       (write-buffered Stderr Newline)
18826       (flush Stderr)
18827       (emit-indent Stderr *(ebp+8))
18828       (write-buffered Stderr "stack offset: ")
18829       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
18830       (write-buffered Stderr Newline)
18831       (flush Stderr)
18832       (emit-indent Stderr *(ebp+8))
18833       (write-buffered Stderr "reg: ")
18834       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
18835       (write-buffered Stderr ",")
18836       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
18837       (write-buffered Stderr "->")
18838       (flush Stderr)
18839       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
18840       (write-int32-hex-buffered Stderr %eax)
18841       {
18842         3d/compare-eax-and 0/imm32
18843         74/jump-if-= break/disp8
18844         (write-buffered Stderr Space)
18845         (write-buffered Stderr %eax)
18846       }
18847       (write-buffered Stderr Newline)
18848       (flush Stderr)
18849     }
18850 $dump-var:end:
18851     # . restore registers
18852     5b/pop-to-ebx
18853     58/pop-to-eax
18854     # . epilogue
18855     89/<- %esp 5/r32/ebp
18856     5d/pop-to-ebp
18857     c3/return
18858 
18859 #######################################################
18860 # Type-checking
18861 #######################################################
18862 
18863 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
18864     # . prologue
18865     55/push-ebp
18866     89/<- %ebp 4/r32/esp
18867     # . save registers
18868     50/push-eax
18869     # var curr/eax: (addr function) = lookup(Program->functions)
18870     (lookup *_Program-functions *_Program-functions->payload)  # => eax
18871     {
18872 $check-mu-types:loop:
18873       # if (curr == null) break
18874       3d/compare-eax-and 0/imm32
18875       0f 84/jump-if-= break/disp32
18876 +--  8 lines: #?       # dump curr->name ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18884       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
18885       # curr = lookup(curr->next)
18886       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
18887       e9/jump loop/disp32
18888     }
18889 $check-mu-types:end:
18890     # . restore registers
18891     58/pop-to-eax
18892     # . epilogue
18893     89/<- %esp 5/r32/ebp
18894     5d/pop-to-ebp
18895     c3/return
18896 
18897 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18898     # . prologue
18899     55/push-ebp
18900     89/<- %ebp 4/r32/esp
18901     # . save registers
18902     50/push-eax
18903     56/push-esi
18904     # esi = f
18905     8b/-> *(ebp+8) 6/r32/esi
18906     # outputs
18907     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
18908     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
18909     # body
18910     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
18911     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
18912     # if function has no outputs, we're done
18913     81 7/subop/compare *(esi+0x10) 0/imm32
18914     74/jump-if-= $check-mu-function:end/disp8
18915     # some final checks on body
18916     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
18917     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
18918 $check-mu-function:end:
18919     # . restore registers
18920     5e/pop-to-esi
18921     58/pop-to-eax
18922     # . epilogue
18923     89/<- %esp 5/r32/ebp
18924     5d/pop-to-ebp
18925     c3/return
18926 
18927 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18928     # . prologue
18929     55/push-ebp
18930     89/<- %ebp 4/r32/esp
18931     # . save registers
18932     50/push-eax
18933     # eax = block
18934     8b/-> *(ebp+8) 0/r32/eax
18935     # var stmts/eax: (addr list stmt) = lookup(block->statements)
18936     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
18937     #
18938     {
18939 $check-mu-block:check-empty:
18940       3d/compare-eax-and 0/imm32
18941       0f 84/jump-if-= break/disp32
18942       # emit block->statements
18943       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18944     }
18945 $check-mu-block:end:
18946     # . restore registers
18947     58/pop-to-eax
18948     # . epilogue
18949     89/<- %esp 5/r32/ebp
18950     5d/pop-to-ebp
18951     c3/return
18952 
18953 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18954     # . prologue
18955     55/push-ebp
18956     89/<- %ebp 4/r32/esp
18957     # . save registers
18958     50/push-eax
18959     56/push-esi
18960     # esi = stmts
18961     8b/-> *(ebp+8) 6/r32/esi
18962     {
18963 $check-mu-stmt-list:loop:
18964       81 7/subop/compare %esi 0/imm32
18965       0f 84/jump-if-= break/disp32
18966       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
18967       (lookup *esi *(esi+4))  # List-value List-value => eax
18968       {
18969 $check-mu-stmt-list:check-for-block:
18970         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
18971         75/jump-if-!= break/disp8
18972 $check-mu-stmt-list:block:
18973         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18974         eb/jump $check-mu-stmt-list:continue/disp8
18975       }
18976       {
18977 $check-mu-stmt-list:check-for-stmt1:
18978         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
18979         0f 85/jump-if-!= break/disp32
18980 $check-mu-stmt-list:stmt1:
18981         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18982         eb/jump $check-mu-stmt-list:continue/disp8
18983       }
18984       {
18985 $check-mu-stmt-list:check-for-reg-var-def:
18986         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
18987         0f 85/jump-if-!= break/disp32
18988 $check-mu-stmt-list:reg-var-def:
18989         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18990         eb/jump $check-mu-stmt-list:continue/disp8
18991       }
18992 $check-mu-stmt-list:continue:
18993       # TODO: raise an error on unrecognized Stmt-tag
18994       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
18995       89/<- %esi 0/r32/eax
18996       e9/jump loop/disp32
18997     }
18998 $check-mu-stmt-list:end:
18999     # . restore registers
19000     5e/pop-to-esi
19001     58/pop-to-eax
19002     # . epilogue
19003     89/<- %esp 5/r32/ebp
19004     5d/pop-to-ebp
19005     c3/return
19006 
19007 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19008     # . prologue
19009     55/push-ebp
19010     89/<- %ebp 4/r32/esp
19011     # . save registers
19012     50/push-eax
19013     # - if stmt's operation matches a primitive, check against it
19014     (has-primitive-name? *(ebp+8))  # => eax
19015     3d/compare-eax-and 0/imm32/false
19016     {
19017       74/jump-if-= break/disp8
19018       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19019       e9/jump $check-mu-stmt:end/disp32
19020     }
19021     # - otherwise find a function to check against
19022     # var f/eax: (addr function) = lookup(*Program->functions)
19023     (lookup *_Program-functions *_Program-functions->payload)  # => eax
19024     (find-matching-function %eax *(ebp+8))  # => eax
19025     3d/compare-eax-and 0/imm32
19026     {
19027       74/jump-if-= break/disp8
19028       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19029       eb/jump $check-mu-stmt:end/disp8
19030     }
19031     # var f/eax: (addr function) = lookup(*Program->signatures)
19032     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
19033     (find-matching-function %eax *(ebp+8))  # => eax
19034     3d/compare-eax-and 0/imm32
19035     {
19036       74/jump-if-= break/disp8
19037       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19038       eb/jump $check-mu-stmt:end/disp8
19039     }
19040     # - otherwise abort
19041     e9/jump $check-mu-stmt:unknown-call/disp32
19042 $check-mu-stmt:end:
19043     # . restore registers
19044     58/pop-to-eax
19045     # . epilogue
19046     89/<- %esp 5/r32/ebp
19047     5d/pop-to-ebp
19048     c3/return
19049 
19050 $check-mu-stmt:unknown-call:
19051     (write-buffered *(ebp+0x10) "unknown function '")
19052     8b/-> *(ebp+8) 0/r32/eax
19053     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
19054     (write-buffered *(ebp+0x10) %eax)
19055     (write-buffered *(ebp+0x10) "'\n")
19056     (flush *(ebp+0x10))
19057     (stop *(ebp+0x14) 1)
19058     # never gets here
19059 
19060 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
19061     # . prologue
19062     55/push-ebp
19063     89/<- %ebp 4/r32/esp
19064     # . save registers
19065     51/push-ecx
19066     56/push-esi
19067     # var name/esi: (addr array byte) = lookup(stmt->operation)
19068     8b/-> *(ebp+8) 6/r32/esi
19069     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
19070     89/<- %esi 0/r32/eax
19071     # if (name == "return") return true
19072     (string-equal? %esi "return")  # => eax
19073     3d/compare-eax-and 0/imm32/false
19074     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19075     # if (name == "get") return true
19076     (string-equal? %esi "get")  # => eax
19077     3d/compare-eax-and 0/imm32/false
19078     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19079     # if (name == "index") return true
19080     (string-equal? %esi "index")  # => eax
19081     3d/compare-eax-and 0/imm32/false
19082     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19083     # if (name == "length") return true
19084     (string-equal? %esi "length")  # => eax
19085     3d/compare-eax-and 0/imm32/false
19086     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19087     # if (name == "compute-offset") return true
19088     (string-equal? %esi "compute-offset")  # => eax
19089     3d/compare-eax-and 0/imm32/false
19090     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19091     # if (name == "copy-object") return true
19092     (string-equal? %esi "copy-object")  # => eax
19093     3d/compare-eax-and 0/imm32/false
19094     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19095     # if (name == "allocate") return true
19096     (string-equal? %esi "allocate")  # => eax
19097     3d/compare-eax-and 0/imm32/false
19098     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19099     # if (name == "populate") return true
19100     (string-equal? %esi "populate")  # => eax
19101     3d/compare-eax-and 0/imm32/false
19102     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19103     # if (name == "populate-stream") return true
19104     (string-equal? %esi "populate-stream")  # => eax
19105     3d/compare-eax-and 0/imm32/false
19106     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19107     # if (name == "read-from-stream") return true
19108     (string-equal? %esi "read-from-stream")  # => eax
19109     3d/compare-eax-and 0/imm32/false
19110     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19111     # if (name == "write-to-stream") return true
19112     (string-equal? %esi "write-to-stream")  # => eax
19113     3d/compare-eax-and 0/imm32/false
19114     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19115     # var curr/ecx: (addr primitive) = Primitives
19116     b9/copy-to-ecx Primitives/imm32
19117     {
19118 $has-primitive-name?:loop:
19119       # if (curr == null) break
19120       81 7/subop/compare %ecx 0/imm32
19121       74/jump-if-= break/disp8
19122       # if (primitive->name == name) return true
19123       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
19124 #?       (write-buffered Stderr %eax)
19125 #?       (write-buffered Stderr Newline)
19126 #?       (flush Stderr)
19127       (string-equal? %esi %eax)  # => eax
19128       3d/compare-eax-and 0/imm32/false
19129       75/jump-if-!= $has-primitive-name?:end/disp8
19130 $has-primitive-name?:next-primitive:
19131       # curr = curr->next
19132       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
19133       89/<- %ecx 0/r32/eax
19134       #
19135       e9/jump loop/disp32
19136     }
19137     # return null
19138     b8/copy-to-eax 0/imm32
19139 $has-primitive-name?:end:
19140     # . restore registers
19141     5e/pop-to-esi
19142     59/pop-to-ecx
19143     # . epilogue
19144     89/<- %esp 5/r32/ebp
19145     5d/pop-to-ebp
19146     c3/return
19147 
19148 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19149     # . prologue
19150     55/push-ebp
19151     89/<- %ebp 4/r32/esp
19152     # . save registers
19153     50/push-eax
19154     51/push-ecx
19155     # var op/ecx: (addr array byte) = lookup(stmt->operation)
19156     8b/-> *(ebp+8) 0/r32/eax
19157     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
19158     89/<- %ecx 0/r32/eax
19159     # if (op == "copy") check-mu-copy-stmt
19160     {
19161       (string-equal? %ecx "copy")  # => eax
19162       3d/compare-eax-and 0/imm32/false
19163       74/jump-if-= break/disp8
19164       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19165       e9/jump $check-mu-primitive:end/disp32
19166     }
19167     # if (op == "copy-to") check-mu-copy-to-stmt
19168     {
19169       (string-equal? %ecx "copy-to")  # => eax
19170       3d/compare-eax-and 0/imm32/false
19171       74/jump-if-= break/disp8
19172       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19173       e9/jump $check-mu-primitive:end/disp32
19174     }
19175     # if (op == "compare") check-mu-compare-stmt
19176     {
19177       (string-equal? %ecx "compare")  # => eax
19178       3d/compare-eax-and 0/imm32/false
19179       74/jump-if-= break/disp8
19180       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19181       e9/jump $check-mu-primitive:end/disp32
19182     }
19183     # if (op == "address") check-mu-address-stmt
19184     {
19185       (string-equal? %ecx "address")  # => eax
19186       3d/compare-eax-and 0/imm32/false
19187       74/jump-if-= break/disp8
19188       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19189       e9/jump $check-mu-primitive:end/disp32
19190     }
19191     # if (op == "return") check-mu-return-stmt
19192     {
19193       (string-equal? %ecx "return")  # => eax
19194       3d/compare-eax-and 0/imm32/false
19195       74/jump-if-= break/disp8
19196       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19197       e9/jump $check-mu-primitive:end/disp32
19198     }
19199     # if (op == "get") check-mu-get-stmt
19200     {
19201       (string-equal? %ecx "get")  # => eax
19202       3d/compare-eax-and 0/imm32/false
19203       74/jump-if-= break/disp8
19204       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19205       e9/jump $check-mu-primitive:end/disp32
19206     }
19207     # if (op == "index") check-mu-index-stmt
19208     {
19209       (string-equal? %ecx "index")  # => eax
19210       3d/compare-eax-and 0/imm32/false
19211       74/jump-if-= break/disp8
19212       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19213       e9/jump $check-mu-primitive:end/disp32
19214     }
19215     # if (op == "length") check-mu-length-stmt
19216     {
19217       (string-equal? %ecx "length")  # => eax
19218       3d/compare-eax-and 0/imm32/false
19219       74/jump-if-= break/disp8
19220       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19221       e9/jump $check-mu-primitive:end/disp32
19222     }
19223     # if (op == "compute-offset") check-mu-compute-offset-stmt
19224     {
19225       (string-equal? %ecx "compute-offset")  # => eax
19226       3d/compare-eax-and 0/imm32/false
19227       74/jump-if-= break/disp8
19228       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19229       e9/jump $check-mu-primitive:end/disp32
19230     }
19231     # if (op == "copy-object") check-mu-copy-object-stmt
19232     {
19233       (string-equal? %ecx "copy-object")  # => eax
19234       3d/compare-eax-and 0/imm32/false
19235       74/jump-if-= break/disp8
19236       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19237       e9/jump $check-mu-primitive:end/disp32
19238     }
19239     # if (op == "allocate") check-mu-allocate-stmt
19240     {
19241       (string-equal? %ecx "allocate")  # => eax
19242       3d/compare-eax-and 0/imm32/false
19243       74/jump-if-= break/disp8
19244       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19245       e9/jump $check-mu-primitive:end/disp32
19246     }
19247     # if (op == "populate") check-mu-populate-stmt
19248     {
19249       (string-equal? %ecx "populate")  # => eax
19250       3d/compare-eax-and 0/imm32/false
19251       74/jump-if-= break/disp8
19252       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19253       e9/jump $check-mu-primitive:end/disp32
19254     }
19255     # if (op == "populate-stream") check-mu-populate-stream-stmt
19256     {
19257       (string-equal? %ecx "populate-stream")  # => eax
19258       3d/compare-eax-and 0/imm32/false
19259       74/jump-if-= break/disp8
19260       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19261       e9/jump $check-mu-primitive:end/disp32
19262     }
19263     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
19264     {
19265       (string-equal? %ecx "read-from-stream")  # => eax
19266       3d/compare-eax-and 0/imm32/false
19267       74/jump-if-= break/disp8
19268       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19269       e9/jump $check-mu-primitive:end/disp32
19270     }
19271     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
19272     {
19273       (string-equal? %ecx "write-to-stream")  # => eax
19274       3d/compare-eax-and 0/imm32/false
19275       74/jump-if-= break/disp8
19276       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19277       e9/jump $check-mu-primitive:end/disp32
19278     }
19279     # if (op == "convert") check-mu-convert-stmt
19280     {
19281       (string-equal? %ecx "convert")  # => eax
19282       3d/compare-eax-and 0/imm32/false
19283       74/jump-if-= break/disp8
19284       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19285       e9/jump $check-mu-primitive:end/disp32
19286     }
19287     # otherwise check-numberlike-stmt
19288     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19289 $check-mu-primitive:end:
19290     # . restore registers
19291     59/pop-to-ecx
19292     58/pop-to-eax
19293     # . epilogue
19294     89/<- %esp 5/r32/ebp
19295     5d/pop-to-ebp
19296     c3/return
19297 
19298 # by default, Mu primitives should only operate on 'number-like' types
19299 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19300     # . prologue
19301     55/push-ebp
19302     89/<- %ebp 4/r32/esp
19303     # . save registers
19304     50/push-eax
19305     51/push-ecx
19306     56/push-esi
19307     # esi = stmt
19308     8b/-> *(ebp+8) 6/r32/esi
19309     # var gas/ecx: int = 2
19310     b9/copy-to-ecx 2/imm32
19311     # - check at most 1 output
19312     # var output/eax: (addr stmt-var) = stmt->outputs
19313     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19314     {
19315       3d/compare-eax-and 0/imm32
19316       74/jump-if-= break/disp8
19317 $check-mu-numberlike-primitive:output:
19318       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19319       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
19320       3d/compare-eax-and 0/imm32
19321       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
19322       # check output is in a register
19323       # --gas
19324       49/decrement-ecx
19325     }
19326     # - check first inout
19327     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19328     {
19329       3d/compare-eax-and 0/imm32
19330       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
19331 $check-mu-numberlike-primitive:first-inout:
19332       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19333       # --gas
19334       49/decrement-ecx
19335     }
19336     # - check second inout
19337     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
19338     {
19339       3d/compare-eax-and 0/imm32
19340       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
19341 $check-mu-numberlike-primitive:second-inout:
19342       # is a second inout allowed?
19343       81 7/subop/compare %ecx 0/imm32
19344       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
19345 $check-mu-numberlike-primitive:second-inout-permitted:
19346       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19347     }
19348 $check-mu-numberlike-primitive:third-inout:
19349     # if there's a third arg, raise an error
19350     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
19351     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
19352 $check-mu-numberlike-primitive:end:
19353     # . restore registers
19354     5e/pop-to-esi
19355     59/pop-to-ecx
19356     58/pop-to-eax
19357     # . epilogue
19358     89/<- %esp 5/r32/ebp
19359     5d/pop-to-ebp
19360     c3/return
19361 
19362 $check-mu-numberlike-primitive:error-too-many-inouts:
19363     (write-buffered *(ebp+0x10) "fn ")
19364     8b/-> *(ebp+0xc) 0/r32/eax
19365     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19366     (write-buffered *(ebp+0x10) %eax)
19367     (write-buffered *(ebp+0x10) ": stmt ")
19368     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
19369     (write-buffered *(ebp+0x10) %eax)
19370     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
19371     (flush *(ebp+0x10))
19372     (stop *(ebp+0x14) 1)
19373     # never gets here
19374 
19375 $check-mu-numberlike-primitive:error-too-many-outputs:
19376     (write-buffered *(ebp+0x10) "fn ")
19377     8b/-> *(ebp+0xc) 0/r32/eax
19378     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19379     (write-buffered *(ebp+0x10) %eax)
19380     (write-buffered *(ebp+0x10) ": stmt ")
19381     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
19382     (write-buffered *(ebp+0x10) %eax)
19383     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
19384     (flush *(ebp+0x10))
19385     (stop *(ebp+0x14) 1)
19386     # never gets here
19387 
19388 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19389     # . prologue
19390     55/push-ebp
19391     89/<- %ebp 4/r32/esp
19392     # . save registers
19393     50/push-eax
19394     56/push-esi
19395     # var t/esi: (addr type-tree) = lookup(v->value->type)
19396     8b/-> *(ebp+8) 0/r32/eax
19397     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19398     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19399     89/<- %esi 0/r32/eax
19400 $check-mu-numberlike-arg:check-literal:
19401     # if t is an int, return
19402     (is-simple-mu-type? %esi 0)  # literal => eax
19403     3d/compare-eax-and 0/imm32/false
19404     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
19405 $check-mu-numberlike-arg:check-addr:
19406     # if t is an addr and v is dereferenced, return whether t->payload is an addr
19407     {
19408       (is-mu-addr-type? %esi)  # => eax
19409       3d/compare-eax-and 0/imm32/false
19410       74/jump-if-= break/disp8
19411       8b/-> *(ebp+8) 0/r32/eax
19412       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
19413       3d/compare-eax-and 0/imm32/false
19414       {
19415         74/jump-if-= break/disp8
19416         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
19417         # if t->right is null, t = t->left
19418         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19419         {
19420           75/jump-if-!= break/disp8
19421           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19422         }
19423         (is-mu-addr-type? %eax)  # => eax
19424         3d/compare-eax-and 0/imm32/false
19425         74/jump-if-= $check-mu-numberlike-arg:end/disp8
19426       }
19427     }
19428 $check-mu-numberlike-arg:output-checks:
19429     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
19430 $check-mu-numberlike-arg:end:
19431     # . restore registers
19432     5e/pop-to-esi
19433     58/pop-to-eax
19434     # . epilogue
19435     89/<- %esp 5/r32/ebp
19436     5d/pop-to-ebp
19437     c3/return
19438 
19439 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19440     # . prologue
19441     55/push-ebp
19442     89/<- %ebp 4/r32/esp
19443     # . save registers
19444     50/push-eax
19445     #
19446     (is-mu-numberlike-output-var? *(ebp+8))  # => eax
19447     3d/compare-eax-and 0/imm32/false
19448     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
19449 $check-mu-numberlike-output:end:
19450     # . restore registers
19451     58/pop-to-eax
19452     # . epilogue
19453     89/<- %esp 5/r32/ebp
19454     5d/pop-to-ebp
19455     c3/return
19456 
19457 $check-mu-numberlike-output:fail:
19458     # otherwise raise an error
19459     (write-buffered *(ebp+0x14) "fn ")
19460     8b/-> *(ebp+0x10) 0/r32/eax
19461     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19462     (write-buffered *(ebp+0x14) %eax)
19463     (write-buffered *(ebp+0x14) ": stmt ")
19464     8b/-> *(ebp+0xc) 0/r32/eax
19465     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
19466     (write-buffered *(ebp+0x14) %eax)
19467     (write-buffered *(ebp+0x14) ": '")
19468     8b/-> *(ebp+8) 0/r32/eax
19469     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19470     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19471     (write-buffered *(ebp+0x14) %eax)
19472     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
19473     (flush *(ebp+0x14))
19474     (stop *(ebp+0x18) 1)
19475     # never gets here
19476 
19477 is-mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
19478     # . prologue
19479     55/push-ebp
19480     89/<- %ebp 4/r32/esp
19481     #
19482     8b/-> *(ebp+8) 0/r32/eax
19483     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19484     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19485     (is-mu-numberlike-output? %eax)  # => eax
19486 $is-mu-numberlike-output-var?:end:
19487     # . epilogue
19488     89/<- %esp 5/r32/ebp
19489     5d/pop-to-ebp
19490     c3/return
19491 
19492 is-mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
19493     # . prologue
19494     55/push-ebp
19495     89/<- %ebp 4/r32/esp
19496     # . save registers
19497     56/push-esi
19498     # var t/esi: (addr type-tree) = lookup(v->value->type)
19499     8b/-> *(ebp+8) 6/r32/esi
19500 $is-mu-numberlike-output?:check-int:
19501     # if t is an int, return
19502     (is-simple-mu-type? %esi 1)  # int => eax
19503     3d/compare-eax-and 0/imm32/false
19504     0f 85/jump-if-!= $is-mu-numberlike-output?:return-true/disp32
19505 $is-mu-numberlike-output?:check-float:
19506     # if t is a float, return
19507     (is-simple-mu-type? %esi 0xf)  # float => eax
19508     3d/compare-eax-and 0/imm32/false
19509     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
19510 $is-mu-numberlike-output?:check-boolean:
19511     # if t is a boolean, return
19512     (is-simple-mu-type? %esi 5)  # boolean => eax
19513     3d/compare-eax-and 0/imm32/false
19514     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
19515 $is-mu-numberlike-output?:check-byte:
19516     # if t is a byte, return
19517     (is-simple-mu-type? %esi 8)  # byte => eax
19518     3d/compare-eax-and 0/imm32/false
19519     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
19520 $is-mu-numberlike-output?:check-code-point:
19521     # if t is a code-point, return
19522     (is-simple-mu-type? %esi 0xd)  # code-point => eax
19523     3d/compare-eax-and 0/imm32/false
19524     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
19525 $is-mu-numberlike-output?:check-grapheme:
19526     # if t is a grapheme, return
19527     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
19528     3d/compare-eax-and 0/imm32/false
19529     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
19530 $is-mu-numberlike-output?:return-false:
19531     b8/copy-to-eax 0/imm32/false
19532     eb/jump $is-mu-numberlike-output?:end/disp8
19533 $is-mu-numberlike-output?:return-true:
19534     b8/copy-to-eax 1/imm32/true
19535 $is-mu-numberlike-output?:end:
19536     # . restore registers
19537     5e/pop-to-esi
19538     # . epilogue
19539     89/<- %esp 5/r32/ebp
19540     5d/pop-to-ebp
19541     c3/return
19542 
19543 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19544     # . prologue
19545     55/push-ebp
19546     89/<- %ebp 4/r32/esp
19547     # . save registers
19548     50/push-eax
19549     51/push-ecx
19550     52/push-edx
19551     56/push-esi
19552     57/push-edi
19553     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
19554     81 5/subop/subtract %esp 0x60/imm32
19555     68/push 0x60/imm32/size
19556     68/push 0/imm32/read
19557     68/push 0/imm32/write
19558     89/<- %edx 4/r32/esp
19559 $check-mu-copy-stmt:get-output:
19560     # esi = stmt
19561     8b/-> *(ebp+8) 6/r32/esi
19562     # var output/edi: (addr stmt-var) = stmt->outputs
19563     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19564     89/<- %edi 0/r32/eax
19565     # zero outputs
19566     3d/compare-eax-and 0/imm32
19567     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
19568     # > 1 output
19569     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19570     3d/compare-eax-and 0/imm32
19571     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
19572 $check-mu-copy-stmt:get-inout:
19573     # var inout/esi: (addr stmt-var) = stmt->inouts
19574     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19575     89/<- %esi 0/r32/eax
19576     # zero inouts
19577     3d/compare-eax-and 0/imm32
19578     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
19579     # > 1 inout
19580     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19581     3d/compare-eax-and 0/imm32
19582     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
19583 $check-mu-copy-stmt:types:
19584     # var inout-type/ecx: (addr type-tree) = inout->value->type
19585     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19586     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19587     89/<- %ecx 0/r32/eax
19588     # if (inout->is-deref?) inout-type = inout-type->payload
19589     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
19590     3d/compare-eax-and 0/imm32/false
19591     {
19592       74/jump-if-= break/disp8
19593       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19594       # if inout-type->right is null, t = inout-type->left
19595       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19596       {
19597         75/jump-if-!= break/disp8
19598         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19599       }
19600       89/<- %ecx 0/r32/eax
19601     }
19602     # if output not in register, abort
19603     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19604     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19605     3d/compare-eax-and 0/imm32
19606     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
19607     # if inout is not a scalar, abort
19608     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19609     (size-of %eax)  # => eax
19610     3d/compare-eax-and 4/imm32
19611     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
19612     # var output-type/eax: (addr type-tree) = output->value->type
19613     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19614     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19615     # if (inout-type == output-type) return
19616     (type-match? %eax %ecx %edx)  # => eax
19617     3d/compare-eax-and 0/imm32
19618     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
19619     # if output is an addr and inout is 0, return
19620     {
19621       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19622       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19623       (is-mu-addr-type? %eax)  # => eax
19624       3d/compare-eax-and 0/imm32/false
19625       74/jump-if-= break/disp8
19626       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19627       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19628       (string-equal? %eax "0")  # => eax
19629       3d/compare-eax-and 0/imm32/false
19630       74/jump-if-= break/disp8
19631       e9/jump $check-mu-copy-stmt:end/disp32
19632     }
19633     # if output is an offset and inout is 0, return
19634     {
19635       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19636       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19637       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
19638       75/jump-if-!= break/disp8
19639       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19640       (is-simple-mu-type? %eax 7)  # offset => eax
19641       3d/compare-eax-and 0/imm32/false
19642       74/jump-if-= break/disp8
19643       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19644       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19645       (string-equal? %eax "0")  # => eax
19646       3d/compare-eax-and 0/imm32/false
19647       74/jump-if-= break/disp8
19648       eb/jump $check-mu-copy-stmt:end/disp8
19649     }
19650     # if output is not number-like, abort
19651     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19652 $check-mu-copy-stmt:end:
19653     # . reclaim locals
19654     81 0/subop/add %esp 0x6c/imm32
19655     # . restore registers
19656     5f/pop-to-edi
19657     5e/pop-to-esi
19658     5a/pop-to-edx
19659     59/pop-to-ecx
19660     58/pop-to-eax
19661     # . epilogue
19662     89/<- %esp 5/r32/ebp
19663     5d/pop-to-ebp
19664     c3/return
19665 
19666 $check-mu-copy-stmt:error-no-inout:
19667     (write-buffered *(ebp+0x10) "fn ")
19668     8b/-> *(ebp+0xc) 0/r32/eax
19669     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19670     (write-buffered *(ebp+0x10) %eax)
19671     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
19672     (flush *(ebp+0x10))
19673     (stop *(ebp+0x14) 1)
19674     # never gets here
19675 
19676 $check-mu-copy-stmt:error-too-many-inouts:
19677     (write-buffered *(ebp+0x10) "fn ")
19678     8b/-> *(ebp+0xc) 0/r32/eax
19679     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19680     (write-buffered *(ebp+0x10) %eax)
19681     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
19682     (flush *(ebp+0x10))
19683     (stop *(ebp+0x14) 1)
19684     # never gets here
19685 
19686 $check-mu-copy-stmt:error-no-output:
19687     (write-buffered *(ebp+0x10) "fn ")
19688     8b/-> *(ebp+0xc) 0/r32/eax
19689     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19690     (write-buffered *(ebp+0x10) %eax)
19691     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
19692     (flush *(ebp+0x10))
19693     (stop *(ebp+0x14) 1)
19694     # never gets here
19695 
19696 $check-mu-copy-stmt:error-output-not-in-register:
19697     (write-buffered *(ebp+0x10) "fn ")
19698     8b/-> *(ebp+0xc) 0/r32/eax
19699     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19700     (write-buffered *(ebp+0x10) %eax)
19701     (write-buffered *(ebp+0x10) ": stmt copy: output '")
19702     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19703     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19704     (write-buffered *(ebp+0x10) %eax)
19705     (write-buffered *(ebp+0x10) "' not in a register\n")
19706     (flush *(ebp+0x10))
19707     (stop *(ebp+0x14) 1)
19708     # never gets here
19709 
19710 $check-mu-copy-stmt:error-too-many-outputs:
19711     (write-buffered *(ebp+0x10) "fn ")
19712     8b/-> *(ebp+0xc) 0/r32/eax
19713     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19714     (write-buffered *(ebp+0x10) %eax)
19715     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
19716     (flush *(ebp+0x10))
19717     (stop *(ebp+0x14) 1)
19718     # never gets here
19719 
19720 $check-mu-copy-stmt:error-inout-too-large:
19721     (write-buffered *(ebp+0x10) "fn ")
19722     8b/-> *(ebp+0xc) 0/r32/eax
19723     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19724     (write-buffered *(ebp+0x10) %eax)
19725     (write-buffered *(ebp+0x10) ": stmt copy: '")
19726     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19727     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19728     (write-buffered *(ebp+0x10) %eax)
19729     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
19730     (flush *(ebp+0x10))
19731     (stop *(ebp+0x14) 1)
19732     # never gets here
19733 
19734 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19735     # . prologue
19736     55/push-ebp
19737     89/<- %ebp 4/r32/esp
19738     # . save registers
19739     50/push-eax
19740     51/push-ecx
19741     52/push-edx
19742     53/push-ebx
19743     56/push-esi
19744     57/push-edi
19745     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
19746     81 5/subop/subtract %esp 0x60/imm32
19747     68/push 0x60/imm32/size
19748     68/push 0/imm32/read
19749     68/push 0/imm32/write
19750     89/<- %edx 4/r32/esp
19751     # esi = stmt
19752     8b/-> *(ebp+8) 6/r32/esi
19753 $check-mu-copy-to-stmt:check-for-output:
19754     # if stmt->outputs abort
19755     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19756     3d/compare-eax-and 0/imm32
19757     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
19758 $check-mu-copy-to-stmt:get-dest:
19759     # var dest/edi: (addr stmt-var) = stmt->inouts
19760     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19761     89/<- %edi 0/r32/eax
19762     # zero inouts
19763     3d/compare-eax-and 0/imm32
19764     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
19765 $check-mu-copy-to-stmt:get-src:
19766     # var src/esi: (addr stmt-var) = dest->next
19767     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19768     89/<- %esi 0/r32/eax
19769     # 1 inout
19770     3d/compare-eax-and 0/imm32
19771     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
19772     # > 2 inouts
19773     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19774     3d/compare-eax-and 0/imm32
19775     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
19776 $check-mu-copy-to-stmt:types:
19777     # var src-type/ecx: (addr type-tree) = src->value->type
19778     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19779     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19780     89/<- %ecx 0/r32/eax
19781     # if src not in register or literal, abort
19782     # (we can't use stack-offset because it hasn't been computed yet)
19783     {
19784       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19785       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
19786       (is-simple-mu-type? %eax 0)  # => eax
19787       3d/compare-eax-and 0/imm32
19788       75/jump-if-!= break/disp8
19789       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19790       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19791       3d/compare-eax-and 0/imm32
19792       75/jump-if-!= break/disp8
19793       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
19794     }
19795     # if src is not a scalar, abort
19796     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19797     (size-of %eax)  # => eax
19798     3d/compare-eax-and 4/imm32
19799     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
19800     # var dest-type/ebx: (addr type-tree) = dest->value->type
19801     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19802     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19803     89/<- %ebx 0/r32/eax
19804     # if (dest->is-deref?) dest-type = dest-type->payload
19805     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
19806     3d/compare-eax-and 0/imm32/false
19807     {
19808       74/jump-if-= break/disp8
19809       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
19810       # if dest-type->right is null, dest-type = dest-type->left
19811       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19812       {
19813         75/jump-if-!= break/disp8
19814         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19815       }
19816       89/<- %ebx 0/r32/eax
19817     }
19818     # if (src-type == dest-type) return
19819     (type-match? %ebx %ecx %edx)  # => eax
19820     3d/compare-eax-and 0/imm32
19821     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
19822     # if dest is an addr and src is 0, return
19823     {
19824       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19825       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19826       (is-mu-addr-type? %eax)  # => eax
19827       3d/compare-eax-and 0/imm32/false
19828       74/jump-if-= break/disp8
19829       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19830       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19831       (string-equal? %eax "0")  # => eax
19832       3d/compare-eax-and 0/imm32/false
19833       74/jump-if-= break/disp8
19834       eb/jump $check-mu-copy-to-stmt:end/disp8
19835     }
19836     # if dest is not number-like, abort
19837     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19838 $check-mu-copy-to-stmt:end:
19839     # . reclaim locals
19840     81 0/subop/add %esp 0x6c/imm32
19841     # . restore registers
19842     5f/pop-to-edi
19843     5e/pop-to-esi
19844     5b/pop-to-ebx
19845     5a/pop-to-edx
19846     59/pop-to-ecx
19847     58/pop-to-eax
19848     # . epilogue
19849     89/<- %esp 5/r32/ebp
19850     5d/pop-to-ebp
19851     c3/return
19852 
19853 $check-mu-copy-to-stmt:error-incorrect-inouts:
19854     (write-buffered *(ebp+0x10) "fn ")
19855     8b/-> *(ebp+0xc) 0/r32/eax
19856     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19857     (write-buffered *(ebp+0x10) %eax)
19858     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
19859     (flush *(ebp+0x10))
19860     (stop *(ebp+0x14) 1)
19861     # never gets here
19862 
19863 $check-mu-copy-to-stmt:error-too-many-outputs:
19864     (write-buffered *(ebp+0x10) "fn ")
19865     8b/-> *(ebp+0xc) 0/r32/eax
19866     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19867     (write-buffered *(ebp+0x10) %eax)
19868     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
19869     (flush *(ebp+0x10))
19870     (stop *(ebp+0x14) 1)
19871     # never gets here
19872 
19873 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
19874     (write-buffered *(ebp+0x10) "fn ")
19875     8b/-> *(ebp+0xc) 0/r32/eax
19876     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19877     (write-buffered *(ebp+0x10) %eax)
19878     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
19879     (flush *(ebp+0x10))
19880     (stop *(ebp+0x14) 1)
19881     # never gets here
19882 
19883 $check-mu-copy-to-stmt:error-src-too-large:
19884     (write-buffered *(ebp+0x10) "fn ")
19885     8b/-> *(ebp+0xc) 0/r32/eax
19886     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19887     (write-buffered *(ebp+0x10) %eax)
19888     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
19889     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19890     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19891     (write-buffered *(ebp+0x10) %eax)
19892     (write-buffered *(ebp+0x10) "' is too large to copy\n")
19893     (flush *(ebp+0x10))
19894     (stop *(ebp+0x14) 1)
19895     # never gets here
19896 
19897 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19898     # . prologue
19899     55/push-ebp
19900     89/<- %ebp 4/r32/esp
19901     # . save registers
19902     50/push-eax
19903     51/push-ecx
19904     52/push-edx
19905     53/push-ebx
19906     56/push-esi
19907     57/push-edi
19908     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
19909     81 5/subop/subtract %esp 0x60/imm32
19910     68/push 0x60/imm32/size
19911     68/push 0/imm32/read
19912     68/push 0/imm32/write
19913     89/<- %edx 4/r32/esp
19914     # esi = stmt
19915     8b/-> *(ebp+8) 6/r32/esi
19916 $check-mu-compare-stmt:check-for-output:
19917     # if stmt->outputs abort
19918     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19919     3d/compare-eax-and 0/imm32
19920     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
19921 $check-mu-compare-stmt:get-left:
19922     # var left/edi: (addr stmt-var) = stmt->inouts
19923     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19924     89/<- %edi 0/r32/eax
19925     # zero inouts
19926     3d/compare-eax-and 0/imm32
19927     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
19928 $check-mu-compare-stmt:get-right:
19929     # var right/esi: (addr stmt-var) = left->next
19930     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
19931     89/<- %esi 0/r32/eax
19932     # 1 inout
19933     3d/compare-eax-and 0/imm32
19934     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
19935     # > 2 inouts
19936     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
19937     3d/compare-eax-and 0/imm32
19938     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
19939     # if both inouts are in memory, abort
19940     {
19941 $check-mu-compare-stmt:both-in-mem:
19942       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19943       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
19944       (is-simple-mu-type? %eax 0)  # => eax
19945       3d/compare-eax-and 0/imm32
19946       0f 85/jump-if-!= break/disp32
19947       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19948       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19949       3d/compare-eax-and 0/imm32
19950       75/jump-if-!= break/disp8
19951       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19952       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
19953       (is-simple-mu-type? %eax 0)  # => eax
19954       3d/compare-eax-and 0/imm32
19955       75/jump-if-!= break/disp8
19956       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19957       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19958       3d/compare-eax-and 0/imm32
19959       75/jump-if-!= break/disp8
19960       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
19961     }
19962 $check-mu-compare-stmt:types:
19963     # var right-type/ecx: (addr type-tree) = right->value->type
19964     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19965     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19966     89/<- %ecx 0/r32/eax
19967     # if (right->is-deref?) right-type = right-type->payload
19968     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
19969     3d/compare-eax-and 0/imm32/false
19970     {
19971       74/jump-if-= break/disp8
19972       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
19973       # if right-type->right is null, right-type = right-type->left
19974       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
19975       {
19976         75/jump-if-!= break/disp8
19977         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19978       }
19979       89/<- %ecx 0/r32/eax
19980     }
19981     # if right is not a scalar, abort
19982     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
19983     (size-of %eax)  # => eax
19984     3d/compare-eax-and 4/imm32
19985     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
19986     # if left is not a scalar, abort
19987     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19988     (size-of %eax)  # => eax
19989     3d/compare-eax-and 4/imm32
19990     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
19991     # var left-type/ebx: (addr type-tree) = left->value->type
19992     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
19993     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19994     89/<- %ebx 0/r32/eax
19995     # if (left->is-deref?) left-type = left-type->payload
19996     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
19997     3d/compare-eax-and 0/imm32/false
19998     {
19999       74/jump-if-= break/disp8
20000       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20001       # if left-type->right is null, left-type = left-type->left
20002       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20003       {
20004         75/jump-if-!= break/disp8
20005         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20006       }
20007       89/<- %ebx 0/r32/eax
20008     }
20009     # if (left-type == right-type) return
20010     (type-match? %ebx %ecx %edx)  # => eax
20011     3d/compare-eax-and 0/imm32
20012     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
20013     # if left is an addr and right is 0, return
20014     {
20015       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20016       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20017       (is-mu-addr-type? %eax)  # => eax
20018       3d/compare-eax-and 0/imm32/false
20019       74/jump-if-= break/disp8
20020       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20021       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20022       (string-equal? %eax "0")  # => eax
20023       3d/compare-eax-and 0/imm32/false
20024       74/jump-if-= break/disp8
20025       eb/jump $check-mu-compare-stmt:end/disp8
20026     }
20027     # if left is not number-like, abort
20028     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20029 $check-mu-compare-stmt:end:
20030     # . reclaim locals
20031     81 0/subop/add %esp 0x6c/imm32
20032     # . restore registers
20033     5f/pop-to-edi
20034     5e/pop-to-esi
20035     5b/pop-to-ebx
20036     5a/pop-to-edx
20037     59/pop-to-ecx
20038     58/pop-to-eax
20039     # . epilogue
20040     89/<- %esp 5/r32/ebp
20041     5d/pop-to-ebp
20042     c3/return
20043 
20044 $check-mu-compare-stmt:error-incorrect-inouts:
20045     (write-buffered *(ebp+0x10) "fn ")
20046     8b/-> *(ebp+0xc) 0/r32/eax
20047     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20048     (write-buffered *(ebp+0x10) %eax)
20049     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
20050     (flush *(ebp+0x10))
20051     (stop *(ebp+0x14) 1)
20052     # never gets here
20053 
20054 $check-mu-compare-stmt:error-too-many-outputs:
20055     (write-buffered *(ebp+0x10) "fn ")
20056     8b/-> *(ebp+0xc) 0/r32/eax
20057     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20058     (write-buffered *(ebp+0x10) %eax)
20059     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
20060     (flush *(ebp+0x10))
20061     (stop *(ebp+0x14) 1)
20062     # never gets here
20063 
20064 $check-mu-compare-stmt:error-both-in-memory:
20065     (write-buffered *(ebp+0x10) "fn ")
20066     8b/-> *(ebp+0xc) 0/r32/eax
20067     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20068     (write-buffered *(ebp+0x10) %eax)
20069     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
20070     (flush *(ebp+0x10))
20071     (stop *(ebp+0x14) 1)
20072     # never gets here
20073 
20074 $check-mu-compare-stmt:error-left-too-large:
20075     (write-buffered *(ebp+0x10) "fn ")
20076     8b/-> *(ebp+0xc) 0/r32/eax
20077     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20078     (write-buffered *(ebp+0x10) %eax)
20079     (write-buffered *(ebp+0x10) ": stmt compare: '")
20080     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20081     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20082     (write-buffered *(ebp+0x10) %eax)
20083     (write-buffered *(ebp+0x10) "' is too large to compare\n")
20084     (flush *(ebp+0x10))
20085     (stop *(ebp+0x14) 1)
20086     # never gets here
20087 
20088 $check-mu-compare-stmt:error-right-too-large:
20089     (write-buffered *(ebp+0x10) "fn ")
20090     8b/-> *(ebp+0xc) 0/r32/eax
20091     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20092     (write-buffered *(ebp+0x10) %eax)
20093     (write-buffered *(ebp+0x10) ": stmt compare: '")
20094     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20095     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20096     (write-buffered *(ebp+0x10) %eax)
20097     (write-buffered *(ebp+0x10) "' is too large to compare\n")
20098     (flush *(ebp+0x10))
20099     (stop *(ebp+0x14) 1)
20100     # never gets here
20101 
20102 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20103     # . prologue
20104     55/push-ebp
20105     89/<- %ebp 4/r32/esp
20106     # . save registers
20107     50/push-eax
20108     51/push-ecx
20109     52/push-edx
20110     56/push-esi
20111     57/push-edi
20112 $check-mu-address-stmt:get-output:
20113     # esi = stmt
20114     8b/-> *(ebp+8) 6/r32/esi
20115     # var output/edi: (addr stmt-var) = stmt->outputs
20116     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20117     89/<- %edi 0/r32/eax
20118     # zero outputs
20119     3d/compare-eax-and 0/imm32
20120     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
20121     # > 1 output
20122     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20123     3d/compare-eax-and 0/imm32
20124     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
20125 $check-mu-address-stmt:get-inout:
20126     # var inout/esi: (addr stmt-var) = stmt->inouts
20127     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20128     89/<- %esi 0/r32/eax
20129     # zero inouts
20130     3d/compare-eax-and 0/imm32
20131     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
20132     # > 1 inout
20133     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20134     3d/compare-eax-and 0/imm32
20135     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
20136 $check-mu-address-stmt:types:
20137     # if output not in register, abort
20138     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20139     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20140     3d/compare-eax-and 0/imm32
20141     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
20142     # var output-type/edx: (addr type-tree) = output->value->type
20143     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20144     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20145     89/<- %edx 0/r32/eax
20146     # if output-type not an addr, abort
20147     (is-mu-addr-type? %edx)  # => eax
20148     3d/compare-eax-and 0/imm32/false
20149     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
20150     # output-type = output-type->right
20151     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
20152     # if output-type->right is null, output-type = output-type->left
20153     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20154     {
20155       75/jump-if-!= break/disp8
20156       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20157     }
20158     89/<- %edx 0/r32/eax
20159     # var inout-type/ecx: (addr type-tree) = inout->value->type
20160     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20161     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20162     89/<- %ecx 0/r32/eax
20163     # if (inout->is-deref?) inout-type = inout-type->payload
20164     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
20165     3d/compare-eax-and 0/imm32/false
20166     {
20167       74/jump-if-= break/disp8
20168       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20169       # if inout-type->right is null, t = inout-type->left
20170       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20171       {
20172         75/jump-if-!= break/disp8
20173         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20174       }
20175       89/<- %ecx 0/r32/eax
20176     }
20177     # if (inout-type != output-type) abort
20178     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
20179     3d/compare-eax-and 0/imm32
20180     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
20181 $check-mu-address-stmt:end:
20182     # . restore registers
20183     5f/pop-to-edi
20184     5e/pop-to-esi
20185     5a/pop-to-edx
20186     59/pop-to-ecx
20187     58/pop-to-eax
20188     # . epilogue
20189     89/<- %esp 5/r32/ebp
20190     5d/pop-to-ebp
20191     c3/return
20192 
20193 $check-mu-address-stmt:error-no-inout:
20194     (write-buffered *(ebp+0x10) "fn ")
20195     8b/-> *(ebp+0xc) 0/r32/eax
20196     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20197     (write-buffered *(ebp+0x10) %eax)
20198     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
20199     (flush *(ebp+0x10))
20200     (stop *(ebp+0x14) 1)
20201     # never gets here
20202 
20203 $check-mu-address-stmt:error-too-many-inouts:
20204     (write-buffered *(ebp+0x10) "fn ")
20205     8b/-> *(ebp+0xc) 0/r32/eax
20206     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20207     (write-buffered *(ebp+0x10) %eax)
20208     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
20209     (flush *(ebp+0x10))
20210     (stop *(ebp+0x14) 1)
20211     # never gets here
20212 
20213 $check-mu-address-stmt:error-no-output:
20214     (write-buffered *(ebp+0x10) "fn ")
20215     8b/-> *(ebp+0xc) 0/r32/eax
20216     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20217     (write-buffered *(ebp+0x10) %eax)
20218     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
20219     (flush *(ebp+0x10))
20220     (stop *(ebp+0x14) 1)
20221     # never gets here
20222 
20223 $check-mu-address-stmt:error-output-not-in-register:
20224     (write-buffered *(ebp+0x10) "fn ")
20225     8b/-> *(ebp+0xc) 0/r32/eax
20226     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20227     (write-buffered *(ebp+0x10) %eax)
20228     (write-buffered *(ebp+0x10) ": stmt address: output '")
20229     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20230     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20231     (write-buffered *(ebp+0x10) %eax)
20232     (write-buffered *(ebp+0x10) "' not in a register\n")
20233     (flush *(ebp+0x10))
20234     (stop *(ebp+0x14) 1)
20235     # never gets here
20236 
20237 $check-mu-address-stmt:error-too-many-outputs:
20238     (write-buffered *(ebp+0x10) "fn ")
20239     8b/-> *(ebp+0xc) 0/r32/eax
20240     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20241     (write-buffered *(ebp+0x10) %eax)
20242     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
20243     (flush *(ebp+0x10))
20244     (stop *(ebp+0x14) 1)
20245     # never gets here
20246 
20247 $check-mu-address-stmt:error-output-not-address:
20248     (write-buffered *(ebp+0x10) "fn ")
20249     8b/-> *(ebp+0xc) 0/r32/eax
20250     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20251     (write-buffered *(ebp+0x10) %eax)
20252     (write-buffered *(ebp+0x10) ": stmt address: output '")
20253     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20254     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20255     (write-buffered *(ebp+0x10) %eax)
20256     (write-buffered *(ebp+0x10) "' is not an addr\n")
20257     (flush *(ebp+0x10))
20258     (stop *(ebp+0x14) 1)
20259     # never gets here
20260 
20261 $check-mu-address-stmt:error-type-mismatch:
20262     (write-buffered *(ebp+0x10) "fn ")
20263     8b/-> *(ebp+0xc) 0/r32/eax
20264     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20265     (write-buffered *(ebp+0x10) %eax)
20266     (write-buffered *(ebp+0x10) ": stmt address: output '")
20267     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20268     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20269     (write-buffered *(ebp+0x10) %eax)
20270     (write-buffered *(ebp+0x10) "' cannot hold address of '")
20271     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20272     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20273     (write-buffered *(ebp+0x10) %eax)
20274     (write-buffered *(ebp+0x10) "'\n")
20275     (flush *(ebp+0x10))
20276     (stop *(ebp+0x14) 1)
20277     # never gets here
20278 
20279 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
20280     # . prologue
20281     55/push-ebp
20282     89/<- %ebp 4/r32/esp
20283     # . save registers
20284     51/push-ecx
20285     52/push-edx
20286     53/push-ebx
20287     # var curr-a/ecx: (addr type-tree) = a
20288     8b/-> *(ebp+8) 1/r32/ecx
20289     # var curr-b/ebx: (addr type-tree) = b
20290     8b/-> *(ebp+0xc) 3/r32/ebx
20291     # if (curr-a->is-atom?) fall back to regular equality
20292     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
20293     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
20294     # if (curr-a->left != curr-b->left) return false
20295     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
20296     89/<- %edx 0/r32/eax
20297     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20298     (type-equal? %edx %eax)  # => eax
20299     3d/compare-eax-and 0/imm32/false
20300     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
20301     # if (curr-a->left == "array") curr-a = curr-a->element-type
20302     {
20303       (is-mu-array? %edx)  # => eax
20304       3d/compare-eax-and 0/imm32/false
20305       75/jump-if-!= break/disp8
20306 $type-equal-ignoring-capacity?:array:
20307       # curr-a = curr-a->right->left
20308       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20309       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20310       89/<- %ecx 0/r32/eax
20311       # curr-b = curr-b->right->left
20312       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20313       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20314       89/<- %ebx 0/r32/eax
20315       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
20316     }
20317     # if (curr-a->left == "stream") curr-a = curr-a->element-type
20318     {
20319       (is-mu-stream? %edx)  # => eax
20320       3d/compare-eax-and 0/imm32/false
20321       75/jump-if-!= break/disp8
20322 $type-equal-ignoring-capacity?:stream:
20323       # curr-a = curr-a->right->left
20324       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20325       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20326       89/<- %ecx 0/r32/eax
20327       # curr-b = curr-b->right->left
20328       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20329       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20330       89/<- %ebx 0/r32/eax
20331       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
20332     }
20333 $type-equal-ignoring-capacity?:base-case:
20334     # return type-equal?(curr-a, curr-b)
20335     (type-equal? %ecx %ebx)  # => eax
20336 $type-equal-ignoring-capacity?:end:
20337     # . restore registers
20338     5b/pop-to-ebx
20339     5a/pop-to-edx
20340     59/pop-to-ecx
20341     # . epilogue
20342     89/<- %esp 5/r32/ebp
20343     5d/pop-to-ebp
20344     c3/return
20345 
20346 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20347     # . prologue
20348     55/push-ebp
20349     89/<- %ebp 4/r32/esp
20350     # . save registers
20351     50/push-eax
20352     51/push-ecx
20353     52/push-edx
20354     53/push-ebx
20355     56/push-esi
20356     57/push-edi
20357     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20358     81 5/subop/subtract %esp 0x60/imm32
20359     68/push 0x60/imm32/size
20360     68/push 0/imm32/read
20361     68/push 0/imm32/write
20362     89/<- %edx 4/r32/esp
20363     # var template/esi: (addr list var) = fn->outputs
20364     8b/-> *(ebp+0xc) 0/r32/eax
20365     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
20366     89/<- %esi 0/r32/eax
20367     # var curr-template/ebx: (addr list var) = fn->outputs
20368     89/<- %ebx 0/r32/eax
20369     # var curr/edi: (addr stmt-var) = stmt->inouts
20370     8b/-> *(ebp+8) 0/r32/eax
20371     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20372     89/<- %edi 0/r32/eax
20373     {
20374       # if template is null, break
20375       81 7/subop/compare %ebx 0/imm32
20376       0f 84/jump-if-= break/disp32
20377       # if curr is null, abort
20378       81 7/subop/compare %edi 0/imm32
20379       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
20380       # var template-type/ecx: (addr type-tree) = template->value->type
20381       (lookup *ebx *(ebx+4))  # List-value List-value => eax
20382       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20383       89/<- %ecx 0/r32/eax
20384       # var curr-type/eax: (addr type-tree) = curr->value->type
20385       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20386       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20387       # if (curr->is-deref?) curr-type = payload of curr-type
20388       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
20389       {
20390         74/jump-if-= break/disp8
20391         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20392         # if t->right is null, t = t->left
20393         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20394         75/jump-if-!= break/disp8
20395         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20396       }
20397       # if (curr-type != template-type) abort
20398       (type-match? %ecx %eax %edx)  # => eax
20399       3d/compare-eax-and 0/imm32/false
20400       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
20401       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
20402       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
20403       3d/compare-eax-and 0/imm32/false
20404       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
20405       # template = template->next
20406       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
20407       89/<- %ebx 0/r32/eax
20408       # curr = curr->next
20409       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20410       89/<- %edi 0/r32/eax
20411       #
20412       e9/jump loop/disp32
20413     }
20414     # if curr is not null, abort
20415     81 7/subop/compare %edi 0/imm32
20416     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
20417 $check-mu-return-stmt:end:
20418     # . reclaim locals
20419     81 0/subop/add %esp 0x6c/imm32
20420     # . restore registers
20421     5f/pop-to-edi
20422     5e/pop-to-esi
20423     5b/pop-to-ebx
20424     5a/pop-to-edx
20425     59/pop-to-ecx
20426     58/pop-to-eax
20427     # . epilogue
20428     89/<- %esp 5/r32/ebp
20429     5d/pop-to-ebp
20430     c3/return
20431 
20432 $check-mu-return-stmt:error1:
20433     (write-buffered *(ebp+0x10) "fn ")
20434     8b/-> *(ebp+0xc) 0/r32/eax
20435     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20436     (write-buffered *(ebp+0x10) %eax)
20437     (write-buffered *(ebp+0x10) ": return: '")
20438     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20439     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20440     (write-buffered *(ebp+0x10) %eax)
20441     (write-buffered *(ebp+0x10) "' has the wrong type\n")
20442     (flush *(ebp+0x10))
20443     (stop *(ebp+0x14) 1)
20444     # never gets here
20445 
20446 $check-mu-return-stmt:error2:
20447     (write-buffered *(ebp+0x10) "fn ")
20448     8b/-> *(ebp+0xc) 0/r32/eax
20449     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20450     (write-buffered *(ebp+0x10) %eax)
20451     (write-buffered *(ebp+0x10) ": return: '")
20452     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20453     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20454     (write-buffered *(ebp+0x10) %eax)
20455     (write-buffered *(ebp+0x10) "' is no longer available\n")
20456     (flush *(ebp+0x10))
20457     (stop *(ebp+0x14) 1)
20458     # never gets here
20459 
20460 $check-mu-return-stmt:error-too-few-inouts:
20461     (write-buffered *(ebp+0x10) "fn ")
20462     8b/-> *(ebp+0xc) 0/r32/eax
20463     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20464     (write-buffered *(ebp+0x10) %eax)
20465     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
20466     (flush *(ebp+0x10))
20467     (stop *(ebp+0x14) 1)
20468     # never gets here
20469 
20470 $check-mu-return-stmt:error-too-many-inouts:
20471     (write-buffered *(ebp+0x10) "fn ")
20472     8b/-> *(ebp+0xc) 0/r32/eax
20473     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20474     (write-buffered *(ebp+0x10) %eax)
20475     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
20476     (flush *(ebp+0x10))
20477     (stop *(ebp+0x14) 1)
20478     # never gets here
20479 
20480 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20481     # . prologue
20482     55/push-ebp
20483     89/<- %ebp 4/r32/esp
20484     # . save registers
20485     50/push-eax
20486     51/push-ecx
20487     56/push-esi
20488     # var table/esi: (addr table (handle array byte) int 8)
20489     81 5/subop/subtract %esp 0x60/imm32
20490     68/push 0x60/imm32/size
20491     68/push 0/imm32/read
20492     68/push 0/imm32/write
20493     89/<- %esi 4/r32/esp
20494     # var curr/ecx: (addr list var) = outputs
20495     8b/-> *(ebp+8) 1/r32/ecx
20496     {
20497       # if (curr == 0) break
20498       81 7/subop/compare %ecx 0/imm32
20499       0f 84/jump-if-= break/disp32
20500       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
20501       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20502       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20503       # if reg exists in table, abort
20504       (maybe-get %esi %eax 0xc)  # => eax
20505       3d/compare-eax-and 0/imm32
20506       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
20507       # insert reg in table
20508       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20509       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20510       (get-or-insert %esi %eax 0xc Heap)
20511       # curr = curr->next
20512       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20513       89/<- %ecx 0/r32/eax
20514       e9/jump loop/disp32
20515     }
20516 $check-all-unique-registers:end:
20517     # . reclaim locals
20518     81 0/subop/add %esp 0x6c/imm32
20519     # . restore registers
20520     5e/pop-to-esi
20521     59/pop-to-ecx
20522     58/pop-to-eax
20523     # . epilogue
20524     89/<- %esp 5/r32/ebp
20525     5d/pop-to-ebp
20526     c3/return
20527 
20528 $check-all-unique-registers:abort:
20529     (write-buffered *(ebp+0x10) "fn ")
20530     8b/-> *(ebp+0xc) 0/r32/eax
20531     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20532     (write-buffered *(ebp+0x10) %eax)
20533     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
20534     (flush *(ebp+0x10))
20535     (stop *(ebp+0x14) 1)
20536     # never gets here
20537 
20538 # return false if s's register is not between start (inclusive) and end (exclusive)
20539 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
20540 # otherwise return true
20541 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
20542     # . prologue
20543     55/push-ebp
20544     89/<- %ebp 4/r32/esp
20545     # . save registers
20546     51/push-ecx
20547     52/push-edx
20548     53/push-ebx
20549     56/push-esi
20550     57/push-edi
20551     # var target/ebx: (addr array byte) = s->value->register
20552     8b/-> *(ebp+8) 0/r32/eax
20553     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20554     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20555 #?     (write-buffered Stderr "AA: ")
20556 #?     (write-buffered Stderr %eax)
20557 #?     (write-buffered Stderr Newline)
20558 #?     (flush Stderr)
20559     # if (var->register == 0) return false
20560     3d/compare-eax-and 0/imm32
20561     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
20562     89/<- %ebx 0/r32/eax
20563     # var curr/ecx: (addr list var) = start
20564     8b/-> *(ebp+0xc) 1/r32/ecx
20565     # edx = end
20566     8b/-> *(ebp+0x10) 2/r32/edx
20567     {
20568       # if (curr == 0) break
20569       81 7/subop/compare %edi 0/imm32
20570       0f 84/jump-if-= break/disp32
20571       # if (curr == end) break
20572       39/compare %ecx 2/r32/edx
20573       0f 84/jump-if-= break/disp32
20574       # var curr-reg/eax: (addr array byte) = curr->value->register
20575       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20576       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20577       # if (curr-reg == 0) continue
20578       3d/compare-eax-and 0/imm32
20579       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
20580       # if (curr-reg == target) check for conflict
20581       (string-equal? %eax %ebx)  # => eax
20582       3d/compare-eax-and 0/imm32/false
20583       {
20584         74/jump-if-= break/disp8
20585 #?         (write-buffered Stderr "conflict?\n")
20586 #?         (flush Stderr)
20587         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
20588         8b/-> *(ebp+0x14) 0/r32/eax
20589         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20590         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
20591         eb/jump $register-within-list-with-conflict?:end/disp8
20592       }
20593 $register-within-list-with-conflict?:continue:
20594       # curr = curr->next
20595       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20596       89/<- %ecx 0/r32/eax
20597       e9/jump loop/disp32
20598     }
20599     # return false
20600     b8/copy-to-eax 0/imm32/false
20601 $register-within-list-with-conflict?:end:
20602     # . restore registers
20603     5f/pop-to-edi
20604     5e/pop-to-esi
20605     5b/pop-to-ebx
20606     5a/pop-to-edx
20607     59/pop-to-ecx
20608     # . epilogue
20609     89/<- %esp 5/r32/ebp
20610     5d/pop-to-ebp
20611     c3/return
20612 
20613 # At the first occurrence of register 'reg' in fn-outputs,
20614 # check if the corresponding element of return-inouts has a different register.
20615 # This hacky helper is intended to be called in one specific place. Don't
20616 # reuse it as is.
20617 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
20618     # . prologue
20619     55/push-ebp
20620     89/<- %ebp 4/r32/esp
20621     # . save registers
20622     51/push-ecx
20623     52/push-edx
20624     53/push-ebx
20625     56/push-esi
20626     57/push-edi
20627 #?     (write-buffered Stderr "BB: ")
20628 #?     (write-buffered Stderr *(ebp+8))
20629 #?     (write-buffered Stderr Newline)
20630 #?     (flush Stderr)
20631     # var curr-output/edi: (addr list var) = fn-outputs
20632     8b/-> *(ebp+0x10) 7/r32/edi
20633     # var curr-inout/esi: (addr stmt-var) = return-inouts
20634     8b/-> *(ebp+0xc) 6/r32/esi
20635     {
20636       # if (curr-output == 0) abort
20637       81 7/subop/compare %edi 0/imm32
20638       0f 84/jump-if-= break/disp32
20639       # if (curr-output->value->register != reg) continue
20640       (lookup *edi *(edi+4))  # List-value List-value => eax
20641       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20642       (string-equal? %eax *(ebp+8))  # => eax
20643       3d/compare-eax-and 0/imm32/false
20644       0f 84/jump-if= $register-conflict?:continue/disp32
20645 #?       (write-buffered Stderr "rescan\n")
20646 #?       (flush Stderr)
20647       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
20648       (lookup *esi *(esi+4))  # List-value List-value => eax
20649       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20650       # if (curr-reg == 0) return true
20651       3d/compare-eax-and 0/imm32
20652       {
20653         75/jump-if-!= break/disp8
20654 #?         (write-buffered Stderr "no register\n")
20655 #?         (flush Stderr)
20656         b8/copy-to-eax 1/imm32/true
20657         e9/jump $register-conflict?:end/disp32
20658       }
20659       # return (curr-reg != reg)
20660       (string-equal? %eax *(ebp+8))  # => eax
20661       3d/compare-eax-and 0/imm32/false
20662       0f 94/set-if-= %al
20663 #?       (write-buffered Stderr "final: ")
20664 #?       (write-int32-hex-buffered Stderr %eax)
20665 #?       (write-buffered Stderr Newline)
20666 #?       (flush Stderr)
20667       eb/jump $register-conflict?:end/disp8
20668 $register-conflict?:continue:
20669       # curr-output = curr-output->next
20670       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
20671       89/<- %edi 0/r32/eax
20672       # curr-inout = curr-inout->next
20673       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20674       89/<- %esi 0/r32/eax
20675       e9/jump loop/disp32
20676     }
20677     # should never get here
20678     (write-buffered Stderr "register-conflict? misused\n")
20679     (flush Stderr)
20680     e8/call syscall_exit/disp32
20681 $register-conflict?:end:
20682     # . restore registers
20683     5f/pop-to-edi
20684     5e/pop-to-esi
20685     5b/pop-to-ebx
20686     5a/pop-to-edx
20687     59/pop-to-ecx
20688     # . epilogue
20689     89/<- %esp 5/r32/ebp
20690     5d/pop-to-ebp
20691     c3/return
20692 
20693 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20694     # . prologue
20695     55/push-ebp
20696     89/<- %ebp 4/r32/esp
20697     # . save registers
20698     50/push-eax
20699     51/push-ecx
20700     # var curr/ecx: (addr list stmt) = block->stmts
20701     8b/-> *(ebp+8) 0/r32/eax
20702     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
20703     3d/compare-eax-and 0/imm32
20704     74/jump-if-= $check-final-stmt-is-return:end/disp8
20705     89/<- %ecx 0/r32/eax
20706     {
20707       # if curr->next == 0, break
20708       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20709       3d/compare-eax-and 0/imm32
20710       74/jump-if-= break/disp8
20711       # curr = curr->next
20712       89/<- %ecx 0/r32/eax
20713       e9/jump loop/disp32
20714     }
20715 $check-final-stmt-is-return:check-tag:
20716     # if curr->value->tag != Stmt1, abort
20717     (lookup *ecx *(ecx+4))  # List-value List-value => eax
20718     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
20719     75/jump-if-!= $check-final-stmt-is-return:error/disp8
20720 $check-final-stmt-is-return:check-operation:
20721     # if curr->operation != "return", abort
20722     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20723     (string-equal? %eax "return")
20724     3d/compare-eax-and 0/imm32/false
20725     74/jump-if-= $check-final-stmt-is-return:error/disp8
20726 $check-final-stmt-is-return:end:
20727     # . restore registers
20728     59/pop-to-ecx
20729     58/pop-to-eax
20730     # . epilogue
20731     89/<- %esp 5/r32/ebp
20732     5d/pop-to-ebp
20733     c3/return
20734 
20735 $check-final-stmt-is-return:error:
20736     (write-buffered *(ebp+0x10) "fn ")
20737     8b/-> *(ebp+0xc) 0/r32/eax
20738     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20739     (write-buffered *(ebp+0x10) %eax)
20740     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
20741     (flush *(ebp+0x10))
20742     (stop *(ebp+0x14) 1)
20743     # never gets here
20744 
20745 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20746     # . prologue
20747     55/push-ebp
20748     89/<- %ebp 4/r32/esp
20749     # . save registers
20750     50/push-eax
20751     51/push-ecx
20752     # var curr/ecx: (addr list stmt) = block->stmts
20753     8b/-> *(ebp+8) 0/r32/eax
20754     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
20755     3d/compare-eax-and 0/imm32
20756     0f 84/jump-if-= $check-no-breaks:end/disp32
20757     89/<- %ecx 0/r32/eax
20758     {
20759       # if curr->next == 0, break
20760       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20761       3d/compare-eax-and 0/imm32
20762       74/jump-if-= break/disp8
20763       # if curr->value->tag != Stmt1, continue
20764       (lookup *ecx *(ecx+4))  # List-value List-value => eax
20765       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
20766       75/jump-if-!= $check-no-breaks:continue/disp8
20767       # if curr->value->operation starts with "break", abort
20768       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20769       (string-starts-with? %eax "break")  # => eax
20770       3d/compare-eax-and 0/imm32/false
20771       75/jump-if-!= $check-no-breaks:error/disp8
20772 $check-no-breaks:continue:
20773       # curr = curr->next
20774       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
20775       89/<- %ecx 0/r32/eax
20776       e9/jump loop/disp32
20777     }
20778 $check-no-breaks:end:
20779     # . restore registers
20780     59/pop-to-ecx
20781     58/pop-to-eax
20782     # . epilogue
20783     89/<- %esp 5/r32/ebp
20784     5d/pop-to-ebp
20785     c3/return
20786 
20787 $check-no-breaks:error:
20788     (write-buffered *(ebp+0x10) "fn ")
20789     8b/-> *(ebp+0xc) 0/r32/eax
20790     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20791     (write-buffered *(ebp+0x10) %eax)
20792     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
20793     (flush *(ebp+0x10))
20794     (stop *(ebp+0x14) 1)
20795     # never gets here
20796 
20797 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20798     # . prologue
20799     55/push-ebp
20800     89/<- %ebp 4/r32/esp
20801     # . save registers
20802     50/push-eax
20803     51/push-ecx
20804     52/push-edx
20805     53/push-ebx
20806     56/push-esi
20807     57/push-edi
20808     # esi = stmt
20809     8b/-> *(ebp+8) 6/r32/esi
20810     # - check for 0 inouts
20811     # var base/ecx: (addr var) = stmt->inouts->value
20812     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20813     3d/compare-eax-and 0/imm32/false
20814     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
20815     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20816     89/<- %ecx 0/r32/eax
20817 $check-mu-get-stmt:check-base:
20818     # - check base type
20819     # if it's an 'addr', check that it's in a register
20820     # var base-type/ebx: (addr type-tree) = lookup(base->type)
20821     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20822     89/<- %ebx 0/r32/eax
20823     {
20824       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
20825       0f 85/jump-if-!= break/disp32
20826 $check-mu-get-stmt:base-is-compound:
20827       # if (type->left != addr) break
20828       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20829       (is-simple-mu-type? %eax 2)  # addr => eax
20830       3d/compare-eax-and 0/imm32/false
20831       74/jump-if-= break/disp8
20832 $check-mu-get-stmt:base-is-addr:
20833       # now check for register
20834       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20835       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
20836 $check-mu-get-stmt:base-is-addr-in-register:
20837       # type->left is now an addr; skip it
20838       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20839       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20840       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
20841 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
20842       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20843       89/<- %ebx 0/r32/eax
20844     }
20845 $check-mu-get-stmt:check-base-typeinfo:
20846     # ensure type is a container
20847     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
20848     {
20849       75/jump-if-!= break/disp8
20850       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
20851       89/<- %ebx 0/r32/eax
20852     }
20853     # var base-type-id/ebx: type-id = base-type->value
20854     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
20855     (is-container? %ebx)  # => eax
20856     3d/compare-eax-and 0/imm32/false
20857     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
20858     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
20859     # . var container/ecx: (handle typeinfo)
20860     68/push 0/imm32
20861     68/push 0/imm32
20862     89/<- %ecx 4/r32/esp
20863     # .
20864     (find-typeinfo %ebx %ecx)
20865     (lookup *ecx *(ecx+4))  # => eax
20866     # . reclaim container
20867     81 0/subop/add %esp 8/imm32
20868     # .
20869     89/<- %edx 0/r32/eax
20870     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
20871     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20872     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20873     89/<- %ecx 0/r32/eax
20874     # - check for 1 inout
20875     3d/compare-eax-and 0/imm32/false
20876     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
20877     # var offset/ecx: (addr var) = lookup(offset->value)
20878     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
20879     89/<- %ecx 0/r32/eax
20880     # - check for valid field
20881     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
20882     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
20883     # - check for too many inouts
20884     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20885     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20886     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20887     3d/compare-eax-and 0/imm32/false
20888     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
20889     # var output/edi: (addr var) = stmt->outputs->value
20890     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20891     # - check for 0 outputs
20892     3d/compare-eax-and 0/imm32/false
20893     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
20894     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20895     89/<- %edi 0/r32/eax
20896 $check-mu-get-stmt:check-output-type:
20897     # - check output type
20898     # must be in register
20899     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
20900     3d/compare-eax-and 0/imm32
20901     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
20902     # must have a non-atomic type
20903     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
20904     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20905     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
20906     # type must start with (addr ...)
20907     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20908     (is-simple-mu-type? %eax 2)  # => eax
20909     3d/compare-eax-and 0/imm32/false
20910     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
20911 $check-mu-get-stmt:check-output-type-match:
20912     # payload of addr type must match 'type' definition
20913     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
20914     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20915     # if (payload->right == null) payload = payload->left
20916     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
20917     {
20918       75/jump-if-!= break/disp8
20919       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20920     }
20921     89/<- %edi 0/r32/eax
20922     # . var output-name/ecx: (addr array byte)
20923     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
20924     89/<- %ecx 0/r32/eax
20925     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
20926     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
20927     (get %eax %ecx 0x10)  # => eax
20928     # .
20929     (lookup *eax *(eax+4))  # => eax
20930     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20931     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20932     # .
20933     (type-equal? %edi %eax)  # => eax
20934     3d/compare-eax-and 0/imm32/false
20935     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
20936     # - check for too many outputs
20937     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20938     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20939     3d/compare-eax-and 0/imm32/false
20940     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
20941 $check-mu-get-stmt:end:
20942     # . restore registers
20943     5f/pop-to-edi
20944     5e/pop-to-esi
20945     5b/pop-to-ebx
20946     5a/pop-to-edx
20947     59/pop-to-ecx
20948     58/pop-to-eax
20949     # . epilogue
20950     89/<- %esp 5/r32/ebp
20951     5d/pop-to-ebp
20952     c3/return
20953 
20954 $check-mu-get-stmt:error-too-few-inouts:
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 get: too few inouts (2 required)\n")
20960     (flush *(ebp+0x10))
20961     (stop *(ebp+0x14) 1)
20962     # never gets here
20963 
20964 $check-mu-get-stmt:error-too-many-inouts:
20965     (write-buffered *(ebp+0x10) "fn ")
20966     8b/-> *(ebp+0xc) 0/r32/eax
20967     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20968     (write-buffered *(ebp+0x10) %eax)
20969     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
20970     (flush *(ebp+0x10))
20971     (stop *(ebp+0x14) 1)
20972     # never gets here
20973 
20974 $check-mu-get-stmt:error-too-few-outputs:
20975     (write-buffered *(ebp+0x10) "fn ")
20976     8b/-> *(ebp+0xc) 0/r32/eax
20977     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20978     (write-buffered *(ebp+0x10) %eax)
20979     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
20980     (flush *(ebp+0x10))
20981     (stop *(ebp+0x14) 1)
20982     # never gets here
20983 
20984 $check-mu-get-stmt:error-too-many-outputs:
20985     (write-buffered *(ebp+0x10) "fn ")
20986     8b/-> *(ebp+0xc) 0/r32/eax
20987     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20988     (write-buffered *(ebp+0x10) %eax)
20989     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
20990     (flush *(ebp+0x10))
20991     (stop *(ebp+0x14) 1)
20992     # never gets here
20993 
20994 $check-mu-get-stmt:error-bad-base:
20995     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
20996     (write-buffered *(ebp+0x10) "fn ")
20997     8b/-> *(ebp+0xc) 0/r32/eax
20998     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20999     (write-buffered *(ebp+0x10) %eax)
21000     (write-buffered *(ebp+0x10) ": stmt get: var '")
21001     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21002     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21003     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21004     (write-buffered *(ebp+0x10) %eax)
21005     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
21006     (flush *(ebp+0x10))
21007     (stop *(ebp+0x14) 1)
21008     # never gets here
21009 
21010 $check-mu-get-stmt:error-base-type-addr-but-not-register:
21011     (write-buffered *(ebp+0x10) "fn ")
21012     8b/-> *(ebp+0xc) 0/r32/eax
21013     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21014     (write-buffered *(ebp+0x10) %eax)
21015     (write-buffered *(ebp+0x10) ": stmt get: var '")
21016     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21017     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21018     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21019     (write-buffered *(ebp+0x10) %eax)
21020     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
21021     (flush *(ebp+0x10))
21022     (stop *(ebp+0x14) 1)
21023     # never gets here
21024 
21025 $check-mu-get-stmt:error-bad-field:
21026     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
21027     (write-buffered *(ebp+0x10) "fn ")
21028     8b/-> *(ebp+0xc) 0/r32/eax
21029     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21030     (write-buffered *(ebp+0x10) %eax)
21031     (write-buffered *(ebp+0x10) ": stmt get: type '")
21032     # . write(Type-id->data[tmp])
21033     bf/copy-to-edi Type-id/imm32
21034     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
21035     {
21036       81 7/subop/compare %esi 0/imm32
21037       74/jump-if-= break/disp8
21038       (write-buffered *(ebp+0x10) %esi)
21039     }
21040     # .
21041     (write-buffered *(ebp+0x10) "' has no member called '")
21042     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21043     (write-buffered *(ebp+0x10) %eax)
21044     (write-buffered *(ebp+0x10) "'\n")
21045     (flush *(ebp+0x10))
21046     (stop *(ebp+0x14) 1)
21047     # never gets here
21048 
21049 $check-mu-get-stmt:error-output-not-in-register:
21050     (write-buffered *(ebp+0x10) "fn ")
21051     8b/-> *(ebp+0xc) 0/r32/eax
21052     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21053     (write-buffered *(ebp+0x10) %eax)
21054     (write-buffered *(ebp+0x10) ": stmt get: output '")
21055     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21056     (write-buffered *(ebp+0x10) %eax)
21057     (write-buffered *(ebp+0x10) "' is not in a register\n")
21058     (flush *(ebp+0x10))
21059     (stop *(ebp+0x14) 1)
21060     # never gets here
21061 
21062 $check-mu-get-stmt:error-output-type-not-address:
21063     (write-buffered *(ebp+0x10) "fn ")
21064     8b/-> *(ebp+0xc) 0/r32/eax
21065     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21066     (write-buffered *(ebp+0x10) %eax)
21067     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
21068     (flush *(ebp+0x10))
21069     (stop *(ebp+0x14) 1)
21070     # never gets here
21071 
21072 $check-mu-get-stmt:error-bad-output-type:
21073     (write-buffered *(ebp+0x10) "fn ")
21074     8b/-> *(ebp+0xc) 0/r32/eax
21075     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21076     (write-buffered *(ebp+0x10) %eax)
21077     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
21078     (write-buffered *(ebp+0x10) %ecx)
21079     (write-buffered *(ebp+0x10) "' of type '")
21080     bf/copy-to-edi Type-id/imm32
21081     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
21082     {
21083       81 7/subop/compare %esi 0/imm32
21084       74/jump-if-= break/disp8
21085       (write-buffered *(ebp+0x10) %esi)
21086     }
21087     (write-buffered *(ebp+0x10) "'\n")
21088     (flush *(ebp+0x10))
21089     (stop *(ebp+0x14) 1)
21090     # never gets here
21091 
21092 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21093     # . prologue
21094     55/push-ebp
21095     89/<- %ebp 4/r32/esp
21096     # . save registers
21097     50/push-eax
21098     51/push-ecx
21099     52/push-edx
21100     53/push-ebx
21101     56/push-esi
21102     57/push-edi
21103     # esi = stmt
21104     8b/-> *(ebp+8) 6/r32/esi
21105     # - check for 0 inouts
21106     # var base/ecx: (addr var) = stmt->inouts->value
21107     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21108 $check-mu-index-stmt:check-no-inouts:
21109     3d/compare-eax-and 0/imm32
21110     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
21111     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21112     89/<- %ecx 0/r32/eax
21113     # - check base type is either (addr array ...) in register or (array ...) on stack
21114     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21115     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21116     89/<- %ebx 0/r32/eax
21117     # if base-type is an atom, abort with a precise error
21118     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21119     {
21120       74/jump-if-= break/disp8
21121       (is-simple-mu-type? %ebx 3)  # array => eax
21122       3d/compare-eax-and 0/imm32/false
21123       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
21124       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
21125     }
21126 $check-mu-index-stmt:base-is-compound:
21127     # if type->left not addr or array, abort
21128     {
21129       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21130       (is-simple-mu-type? %eax 2)  # addr => eax
21131       3d/compare-eax-and 0/imm32/false
21132       75/jump-if-!= break/disp8
21133       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21134       (is-simple-mu-type? %eax 3)  # array => eax
21135       3d/compare-eax-and 0/imm32/false
21136       75/jump-if-!= break/disp8
21137       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
21138     }
21139     # if (type->left == addr) ensure type->right->left == array and type->register exists
21140     {
21141       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21142       (is-simple-mu-type? %eax 2)  # addr => eax
21143       3d/compare-eax-and 0/imm32/false
21144       74/jump-if-= break/disp8
21145 $check-mu-index-stmt:base-is-addr:
21146       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21147       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21148       (is-simple-mu-type? %eax 3)  # array => eax
21149       3d/compare-eax-and 0/imm32/false
21150       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
21151 $check-mu-index-stmt:check-base-addr-is-register:
21152       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21153       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
21154     }
21155     # if (type->left == array) ensure type->register doesn't exist
21156     {
21157       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21158       (is-simple-mu-type? %eax 3)  # array => eax
21159       3d/compare-eax-and 0/imm32/false
21160       74/jump-if-= break/disp8
21161 $check-mu-index-stmt:base-is-array:
21162       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21163       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
21164     }
21165     # if (base-type->left == addr) base-type = base-type->right
21166     {
21167       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21168       (is-simple-mu-type? %eax 2)  # addr => eax
21169       3d/compare-eax-and 0/imm32/false
21170       74/jump-if-= break/disp8
21171       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21172       89/<- %ebx 0/r32/eax
21173     }
21174     # - check for 1 inout
21175     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
21176     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21177     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21178 $check-mu-index-stmt:check-single-inout:
21179     3d/compare-eax-and 0/imm32
21180     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
21181     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21182     89/<- %ecx 0/r32/eax
21183     # - check index is either a literal or register
21184     # var index-type/edx: (addr type-tree)
21185     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21186     89/<- %edx 0/r32/eax
21187     # if index type is an atom, it must be a literal or int
21188     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21189     {
21190       74/jump-if-= break/disp8
21191 $check-mu-index-stmt:index-type-is-atom:
21192       (is-simple-mu-type? %edx 0)  # literal => eax
21193       3d/compare-eax-and 0/imm32/false
21194       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
21195       (is-simple-mu-type? %edx 1)  # int => eax
21196       3d/compare-eax-and 0/imm32/false
21197       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
21198       (is-simple-mu-type? %edx 7)  # offset => eax
21199       3d/compare-eax-and 0/imm32/false
21200       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
21201       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
21202     }
21203     # if index type is a non-atom: it must be an offset
21204     {
21205       75/jump-if-!= break/disp8
21206 $check-mu-index-stmt:index-type-is-non-atom:
21207       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
21208       (is-simple-mu-type? %eax 7)  # offset => eax
21209       3d/compare-eax-and 0/imm32/false
21210       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
21211     }
21212 $check-mu-index-stmt:index-type-done:
21213     # check index is either a literal or in a register
21214     {
21215       (is-simple-mu-type? %edx 0)  # literal => eax
21216       3d/compare-eax-and 0/imm32/false
21217       75/jump-if-!= break/disp8
21218 $check-mu-index-stmt:check-index-in-register:
21219       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21220       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
21221     }
21222     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
21223     {
21224       (is-simple-mu-type? %edx 1)  # int => eax
21225       3d/compare-eax-and 0/imm32/false
21226       74/jump-if-= break/disp8
21227 $check-mu-index-stmt:check-index-can-be-int:
21228       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21229       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21230       (array-element-size %eax)  # => eax
21231       3d/compare-eax-and 1/imm32
21232       74/jump-if-= break/disp8
21233       3d/compare-eax-and 2/imm32
21234       74/jump-if-= break/disp8
21235       3d/compare-eax-and 4/imm32
21236       74/jump-if-= break/disp8
21237       3d/compare-eax-and 8/imm32
21238       74/jump-if-= break/disp8
21239       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
21240     }
21241     # - check for too many inouts
21242     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21243     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21244     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21245     3d/compare-eax-and 0/imm32/false
21246     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
21247     # - check for 0 outputs
21248     # var output/edi: (addr var) = stmt->outputs->value
21249     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21250     3d/compare-eax-and 0/imm32/false
21251     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
21252     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21253     89/<- %edi 0/r32/eax
21254     # - check output type
21255     # must have a non-atomic type
21256     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21257     89/<- %edx 0/r32/eax
21258     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21259     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
21260     # type must start with (addr ...)
21261     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
21262     (is-simple-mu-type? %eax 2)  # addr => eax
21263     3d/compare-eax-and 0/imm32/false
21264     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
21265     # if tail(base-type) != tail(output-type) abort
21266     (type-tail %ebx)  # => eax
21267     89/<- %ebx 0/r32/eax
21268     (type-tail %edx)  # => eax
21269     (type-equal? %ebx %eax)  # => eax
21270     3d/compare-eax-and 0/imm32/false
21271     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
21272     # - check for too many outputs
21273     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21274     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21275     3d/compare-eax-and 0/imm32/false
21276     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
21277 $check-mu-index-stmt:end:
21278     # . restore registers
21279     5f/pop-to-edi
21280     5e/pop-to-esi
21281     5b/pop-to-ebx
21282     5a/pop-to-edx
21283     59/pop-to-ecx
21284     58/pop-to-eax
21285     # . epilogue
21286     89/<- %esp 5/r32/ebp
21287     5d/pop-to-ebp
21288     c3/return
21289 
21290 $check-mu-index-stmt:error-base-non-array-type:
21291     (write-buffered *(ebp+0x10) "fn ")
21292     8b/-> *(ebp+0xc) 0/r32/eax
21293     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21294     (write-buffered *(ebp+0x10) %eax)
21295     (write-buffered *(ebp+0x10) ": stmt index: var '")
21296     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21297     (write-buffered *(ebp+0x10) %eax)
21298     (write-buffered *(ebp+0x10) "' is not an array\n")
21299     (flush *(ebp+0x10))
21300     (stop *(ebp+0x14) 1)
21301     # never gets here
21302 
21303 $check-mu-index-stmt:error-base-array-atom-type:
21304     (write-buffered *(ebp+0x10) "fn ")
21305     8b/-> *(ebp+0xc) 0/r32/eax
21306     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21307     (write-buffered *(ebp+0x10) %eax)
21308     (write-buffered *(ebp+0x10) ": stmt index: array '")
21309     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21310     (write-buffered *(ebp+0x10) %eax)
21311     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
21312     (flush *(ebp+0x10))
21313     (stop *(ebp+0x14) 1)
21314     # never gets here
21315 
21316 $check-mu-index-stmt:error-base-address-array-type-on-stack:
21317     (write-buffered *(ebp+0x10) "fn ")
21318     8b/-> *(ebp+0xc) 0/r32/eax
21319     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21320     (write-buffered *(ebp+0x10) %eax)
21321     (write-buffered *(ebp+0x10) ": stmt index: var '")
21322     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21323     (write-buffered *(ebp+0x10) %eax)
21324     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
21325     (flush *(ebp+0x10))
21326     (stop *(ebp+0x14) 1)
21327     # never gets here
21328 
21329 $check-mu-index-stmt:error-base-array-type-in-register:
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 index: var '")
21335     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21336     (write-buffered *(ebp+0x10) %eax)
21337     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
21338     (flush *(ebp+0x10))
21339     (stop *(ebp+0x14) 1)
21340     # never gets here
21341 
21342 $check-mu-index-stmt:error-too-few-inouts:
21343     (write-buffered *(ebp+0x10) "fn ")
21344     8b/-> *(ebp+0xc) 0/r32/eax
21345     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21346     (write-buffered *(ebp+0x10) %eax)
21347     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
21348     (flush *(ebp+0x10))
21349     (stop *(ebp+0x14) 1)
21350     # never gets here
21351 
21352 $check-mu-index-stmt:error-invalid-index-type:
21353     (write-buffered *(ebp+0x10) "fn ")
21354     8b/-> *(ebp+0xc) 0/r32/eax
21355     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21356     (write-buffered *(ebp+0x10) %eax)
21357     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
21358     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21359     (write-buffered *(ebp+0x10) %eax)
21360     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
21361     (flush *(ebp+0x10))
21362     (stop *(ebp+0x14) 1)
21363     # never gets here
21364 
21365 $check-mu-index-stmt:error-index-offset-atom-type:
21366     (write-buffered *(ebp+0x10) "fn ")
21367     8b/-> *(ebp+0xc) 0/r32/eax
21368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21369     (write-buffered *(ebp+0x10) %eax)
21370     (write-buffered *(ebp+0x10) ": stmt index: offset '")
21371     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21372     (write-buffered *(ebp+0x10) %eax)
21373     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
21374     (flush *(ebp+0x10))
21375     (stop *(ebp+0x14) 1)
21376     # never gets here
21377 
21378 $check-mu-index-stmt:error-index-on-stack:
21379     (write-buffered *(ebp+0x10) "fn ")
21380     8b/-> *(ebp+0xc) 0/r32/eax
21381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21382     (write-buffered *(ebp+0x10) %eax)
21383     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
21384     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21385     (write-buffered *(ebp+0x10) %eax)
21386     (write-buffered *(ebp+0x10) "' must be in a register\n")
21387     (flush *(ebp+0x10))
21388     (stop *(ebp+0x14) 1)
21389     # never gets here
21390 
21391 $check-mu-index-stmt:error-index-needs-offset:
21392     (write-buffered *(ebp+0x10) "fn ")
21393     8b/-> *(ebp+0xc) 0/r32/eax
21394     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21395     (write-buffered *(ebp+0x10) %eax)
21396     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
21397     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21398     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21399     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21400     (write-buffered *(ebp+0x10) %eax)
21401     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
21402     (flush *(ebp+0x10))
21403     (stop *(ebp+0x14) 1)
21404     # never gets here
21405 
21406 $check-mu-index-stmt:error-too-many-inouts:
21407     (write-buffered *(ebp+0x10) "fn ")
21408     8b/-> *(ebp+0xc) 0/r32/eax
21409     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21410     (write-buffered *(ebp+0x10) %eax)
21411     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
21412     (flush *(ebp+0x10))
21413     (stop *(ebp+0x14) 1)
21414     # never gets here
21415 
21416 $check-mu-index-stmt:error-too-few-outputs:
21417     (write-buffered *(ebp+0x10) "fn ")
21418     8b/-> *(ebp+0xc) 0/r32/eax
21419     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21420     (write-buffered *(ebp+0x10) %eax)
21421     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
21422     (flush *(ebp+0x10))
21423     (stop *(ebp+0x14) 1)
21424     # never gets here
21425 
21426 $check-mu-index-stmt:error-too-many-outputs:
21427     (write-buffered *(ebp+0x10) "fn ")
21428     8b/-> *(ebp+0xc) 0/r32/eax
21429     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21430     (write-buffered *(ebp+0x10) %eax)
21431     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
21432     (flush *(ebp+0x10))
21433     (stop *(ebp+0x14) 1)
21434     # never gets here
21435 
21436 $check-mu-index-stmt:error-output-not-in-register:
21437     (write-buffered *(ebp+0x10) "fn ")
21438     8b/-> *(ebp+0xc) 0/r32/eax
21439     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21440     (write-buffered *(ebp+0x10) %eax)
21441     (write-buffered *(ebp+0x10) ": stmt index: output '")
21442     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21443     (write-buffered *(ebp+0x10) %eax)
21444     (write-buffered *(ebp+0x10) "' is not in a register\n")
21445     (flush *(ebp+0x10))
21446     (stop *(ebp+0x14) 1)
21447     # never gets here
21448 
21449 $check-mu-index-stmt:error-output-type-not-address:
21450     (write-buffered *(ebp+0x10) "fn ")
21451     8b/-> *(ebp+0xc) 0/r32/eax
21452     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21453     (write-buffered *(ebp+0x10) %eax)
21454     (write-buffered *(ebp+0x10) ": stmt index: output '")
21455     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21456     (write-buffered *(ebp+0x10) %eax)
21457     (write-buffered *(ebp+0x10) "' must be an addr\n")
21458     (flush *(ebp+0x10))
21459     (stop *(ebp+0x14) 1)
21460     # never gets here
21461 
21462 $check-mu-index-stmt:error-bad-output-type:
21463     (write-buffered *(ebp+0x10) "fn ")
21464     8b/-> *(ebp+0xc) 0/r32/eax
21465     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21466     (write-buffered *(ebp+0x10) %eax)
21467     (write-buffered *(ebp+0x10) ": stmt index: output '")
21468     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21469     (write-buffered *(ebp+0x10) %eax)
21470     (write-buffered *(ebp+0x10) "' does not have the right type\n")
21471     (flush *(ebp+0x10))
21472     (stop *(ebp+0x14) 1)
21473     # never gets here
21474 
21475 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21476     # . prologue
21477     55/push-ebp
21478     89/<- %ebp 4/r32/esp
21479     # . save registers
21480     50/push-eax
21481     51/push-ecx
21482     52/push-edx
21483     53/push-ebx
21484     56/push-esi
21485     57/push-edi
21486     # esi = stmt
21487     8b/-> *(ebp+8) 6/r32/esi
21488     # - check for 0 inouts
21489     # var base/ecx: (addr var) = stmt->inouts->value
21490     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21491 $check-mu-length-stmt:check-no-inouts:
21492     3d/compare-eax-and 0/imm32
21493     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
21494     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21495     89/<- %ecx 0/r32/eax
21496     # - check base type is either (addr array ...) in register or (array ...) on stack
21497     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21498     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21499     89/<- %ebx 0/r32/eax
21500     # if base-type is an atom, abort with a precise error
21501     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21502     {
21503       74/jump-if-= break/disp8
21504       (is-simple-mu-type? %ebx 3)  # array => eax
21505       3d/compare-eax-and 0/imm32/false
21506       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
21507       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
21508     }
21509 $check-mu-length-stmt:base-is-compound:
21510     # if type->left not addr or array, abort
21511     {
21512       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21513       (is-simple-mu-type? %eax 2)  # addr => eax
21514       3d/compare-eax-and 0/imm32/false
21515       75/jump-if-!= break/disp8
21516       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21517       (is-simple-mu-type? %eax 3)  # array => eax
21518       3d/compare-eax-and 0/imm32/false
21519       75/jump-if-!= break/disp8
21520       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
21521     }
21522     # if (type->left == addr) ensure type->right->left == array and type->register exists
21523     {
21524       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21525       (is-simple-mu-type? %eax 2)  # addr => eax
21526       3d/compare-eax-and 0/imm32/false
21527       74/jump-if-= break/disp8
21528 $check-mu-length-stmt:base-is-addr:
21529       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21530       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21531       (is-simple-mu-type? %eax 3)  # array => eax
21532       3d/compare-eax-and 0/imm32/false
21533       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
21534 $check-mu-length-stmt:check-base-addr-is-register:
21535       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21536       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
21537     }
21538     # if (type->left == array) ensure type->register doesn't exist
21539     {
21540       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21541       (is-simple-mu-type? %eax 3)  # array => eax
21542       3d/compare-eax-and 0/imm32/false
21543       74/jump-if-= break/disp8
21544 $check-mu-length-stmt:base-is-array:
21545       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21546       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
21547     }
21548     # if (base-type->left == addr) base-type = base-type->right
21549     {
21550       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21551       (is-simple-mu-type? %eax 2)  # addr => eax
21552       3d/compare-eax-and 0/imm32/false
21553       74/jump-if-= break/disp8
21554       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21555       89/<- %ebx 0/r32/eax
21556     }
21557     # - check for too many inouts
21558     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21559     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21560     3d/compare-eax-and 0/imm32/false
21561     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
21562     # - check for 0 outputs
21563     # var output/edi: (addr var) = stmt->outputs->value
21564     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21565     3d/compare-eax-and 0/imm32/false
21566     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
21567     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21568     89/<- %edi 0/r32/eax
21569     # - check output type
21570     # must have a non-atomic type
21571     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21572     (is-simple-mu-type? %eax 1)  # int => eax
21573     3d/compare-eax-and 0/imm32/false
21574     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
21575     # - check for too many outputs
21576     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21577     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21578     3d/compare-eax-and 0/imm32/false
21579     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
21580 $check-mu-length-stmt:end:
21581     # . restore registers
21582     5f/pop-to-edi
21583     5e/pop-to-esi
21584     5b/pop-to-ebx
21585     5a/pop-to-edx
21586     59/pop-to-ecx
21587     58/pop-to-eax
21588     # . epilogue
21589     89/<- %esp 5/r32/ebp
21590     5d/pop-to-ebp
21591     c3/return
21592 
21593 $check-mu-length-stmt:error-base-non-array-type:
21594     (write-buffered *(ebp+0x10) "fn ")
21595     8b/-> *(ebp+0xc) 0/r32/eax
21596     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21597     (write-buffered *(ebp+0x10) %eax)
21598     (write-buffered *(ebp+0x10) ": stmt length: var '")
21599     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21600     (write-buffered *(ebp+0x10) %eax)
21601     (write-buffered *(ebp+0x10) "' is not an array\n")
21602     (flush *(ebp+0x10))
21603     (stop *(ebp+0x14) 1)
21604     # never gets here
21605 
21606 $check-mu-length-stmt:error-base-array-atom-type:
21607     (write-buffered *(ebp+0x10) "fn ")
21608     8b/-> *(ebp+0xc) 0/r32/eax
21609     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21610     (write-buffered *(ebp+0x10) %eax)
21611     (write-buffered *(ebp+0x10) ": stmt length: array '")
21612     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21613     (write-buffered *(ebp+0x10) %eax)
21614     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
21615     (flush *(ebp+0x10))
21616     (stop *(ebp+0x14) 1)
21617     # never gets here
21618 
21619 $check-mu-length-stmt:error-base-address-array-type-on-stack:
21620     (write-buffered *(ebp+0x10) "fn ")
21621     8b/-> *(ebp+0xc) 0/r32/eax
21622     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21623     (write-buffered *(ebp+0x10) %eax)
21624     (write-buffered *(ebp+0x10) ": stmt length: var '")
21625     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21626     (write-buffered *(ebp+0x10) %eax)
21627     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
21628     (flush *(ebp+0x10))
21629     (stop *(ebp+0x14) 1)
21630     # never gets here
21631 
21632 $check-mu-length-stmt:error-base-array-type-in-register:
21633     (write-buffered *(ebp+0x10) "fn ")
21634     8b/-> *(ebp+0xc) 0/r32/eax
21635     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21636     (write-buffered *(ebp+0x10) %eax)
21637     (write-buffered *(ebp+0x10) ": stmt length: var '")
21638     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21639     (write-buffered *(ebp+0x10) %eax)
21640     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
21641     (flush *(ebp+0x10))
21642     (stop *(ebp+0x14) 1)
21643     # never gets here
21644 
21645 $check-mu-length-stmt:error-too-few-inouts:
21646     (write-buffered *(ebp+0x10) "fn ")
21647     8b/-> *(ebp+0xc) 0/r32/eax
21648     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21649     (write-buffered *(ebp+0x10) %eax)
21650     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
21651     (flush *(ebp+0x10))
21652     (stop *(ebp+0x14) 1)
21653     # never gets here
21654 
21655 $check-mu-length-stmt:error-invalid-index-type:
21656     (write-buffered *(ebp+0x10) "fn ")
21657     8b/-> *(ebp+0xc) 0/r32/eax
21658     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21659     (write-buffered *(ebp+0x10) %eax)
21660     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
21661     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21662     (write-buffered *(ebp+0x10) %eax)
21663     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
21664     (flush *(ebp+0x10))
21665     (stop *(ebp+0x14) 1)
21666     # never gets here
21667 
21668 $check-mu-length-stmt:error-index-offset-atom-type:
21669     (write-buffered *(ebp+0x10) "fn ")
21670     8b/-> *(ebp+0xc) 0/r32/eax
21671     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21672     (write-buffered *(ebp+0x10) %eax)
21673     (write-buffered *(ebp+0x10) ": stmt length: offset '")
21674     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21675     (write-buffered *(ebp+0x10) %eax)
21676     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
21677     (flush *(ebp+0x10))
21678     (stop *(ebp+0x14) 1)
21679     # never gets here
21680 
21681 $check-mu-length-stmt:error-index-on-stack:
21682     (write-buffered *(ebp+0x10) "fn ")
21683     8b/-> *(ebp+0xc) 0/r32/eax
21684     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21685     (write-buffered *(ebp+0x10) %eax)
21686     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
21687     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21688     (write-buffered *(ebp+0x10) %eax)
21689     (write-buffered *(ebp+0x10) "' must be in a register\n")
21690     (flush *(ebp+0x10))
21691     (stop *(ebp+0x14) 1)
21692     # never gets here
21693 
21694 $check-mu-length-stmt:error-index-needs-offset:
21695     (write-buffered *(ebp+0x10) "fn ")
21696     8b/-> *(ebp+0xc) 0/r32/eax
21697     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21698     (write-buffered *(ebp+0x10) %eax)
21699     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
21700     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21701     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21702     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21703     (write-buffered *(ebp+0x10) %eax)
21704     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
21705     (flush *(ebp+0x10))
21706     (stop *(ebp+0x14) 1)
21707     # never gets here
21708 
21709 $check-mu-length-stmt:error-too-many-inouts:
21710     (write-buffered *(ebp+0x10) "fn ")
21711     8b/-> *(ebp+0xc) 0/r32/eax
21712     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21713     (write-buffered *(ebp+0x10) %eax)
21714     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
21715     (flush *(ebp+0x10))
21716     (stop *(ebp+0x14) 1)
21717     # never gets here
21718 
21719 $check-mu-length-stmt:error-too-few-outputs:
21720     (write-buffered *(ebp+0x10) "fn ")
21721     8b/-> *(ebp+0xc) 0/r32/eax
21722     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21723     (write-buffered *(ebp+0x10) %eax)
21724     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
21725     (flush *(ebp+0x10))
21726     (stop *(ebp+0x14) 1)
21727     # never gets here
21728 
21729 $check-mu-length-stmt:error-too-many-outputs:
21730     (write-buffered *(ebp+0x10) "fn ")
21731     8b/-> *(ebp+0xc) 0/r32/eax
21732     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21733     (write-buffered *(ebp+0x10) %eax)
21734     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
21735     (flush *(ebp+0x10))
21736     (stop *(ebp+0x14) 1)
21737     # never gets here
21738 
21739 $check-mu-length-stmt:error-output-not-in-register:
21740     (write-buffered *(ebp+0x10) "fn ")
21741     8b/-> *(ebp+0xc) 0/r32/eax
21742     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21743     (write-buffered *(ebp+0x10) %eax)
21744     (write-buffered *(ebp+0x10) ": stmt length: output '")
21745     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21746     (write-buffered *(ebp+0x10) %eax)
21747     (write-buffered *(ebp+0x10) "' is not in a register\n")
21748     (flush *(ebp+0x10))
21749     (stop *(ebp+0x14) 1)
21750     # never gets here
21751 
21752 $check-mu-length-stmt:error-invalid-output-type:
21753     (write-buffered *(ebp+0x10) "fn ")
21754     8b/-> *(ebp+0xc) 0/r32/eax
21755     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21756     (write-buffered *(ebp+0x10) %eax)
21757     (write-buffered *(ebp+0x10) ": stmt length: output '")
21758     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21759     (write-buffered *(ebp+0x10) %eax)
21760     (write-buffered *(ebp+0x10) "' does not have the right type\n")
21761     (flush *(ebp+0x10))
21762     (stop *(ebp+0x14) 1)
21763     # never gets here
21764 
21765 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21766     # . prologue
21767     55/push-ebp
21768     89/<- %ebp 4/r32/esp
21769     # . save registers
21770     50/push-eax
21771     51/push-ecx
21772     52/push-edx
21773     53/push-ebx
21774     56/push-esi
21775     57/push-edi
21776     # esi = stmt
21777     8b/-> *(ebp+8) 6/r32/esi
21778     # - check for 0 inouts
21779     # var base/ecx: (addr var) = stmt->inouts->value
21780     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21781 $check-mu-compute-offset-stmt:check-no-inouts:
21782     3d/compare-eax-and 0/imm32
21783     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
21784     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21785     89/<- %ecx 0/r32/eax
21786     # - check base type is either (addr array ...) in register or (array ...) on stack
21787     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21788     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21789     89/<- %ebx 0/r32/eax
21790     # if base-type is an atom, abort with a precise error
21791     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21792     {
21793       74/jump-if-= break/disp8
21794       (is-simple-mu-type? %ebx 3)  # array => eax
21795       3d/compare-eax-and 0/imm32/false
21796       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
21797       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
21798     }
21799 $check-mu-compute-offset-stmt:base-is-compound:
21800     # if type->left not addr or array, abort
21801     {
21802       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21803       (is-simple-mu-type? %eax 2)  # addr => eax
21804       3d/compare-eax-and 0/imm32/false
21805       75/jump-if-!= break/disp8
21806       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21807       (is-simple-mu-type? %eax 3)  # array => eax
21808       3d/compare-eax-and 0/imm32/false
21809       75/jump-if-!= break/disp8
21810       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
21811     }
21812     # if (type->left == addr) ensure type->right->left == array and type->register exists
21813     {
21814       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21815       (is-simple-mu-type? %eax 2)  # addr => eax
21816       3d/compare-eax-and 0/imm32/false
21817       74/jump-if-= break/disp8
21818 $check-mu-compute-offset-stmt:base-is-addr:
21819       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21820       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21821       (is-simple-mu-type? %eax 3)  # array => eax
21822       3d/compare-eax-and 0/imm32/false
21823       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
21824     }
21825     # if (base-type->left == addr) base-type = base-type->right
21826     {
21827       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21828       (is-simple-mu-type? %eax 2)  # addr => eax
21829       3d/compare-eax-and 0/imm32/false
21830       74/jump-if-= break/disp8
21831       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21832       89/<- %ebx 0/r32/eax
21833     }
21834     # - check for 1 inout
21835     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
21836     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21837     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21838 $check-mu-compute-offset-stmt:check-single-inout:
21839     3d/compare-eax-and 0/imm32
21840     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
21841     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21842     89/<- %ecx 0/r32/eax
21843     # - check index is either a literal or register
21844     # var index-type/edx: (addr type-tree)
21845     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21846     89/<- %edx 0/r32/eax
21847     # index type must be a literal or int
21848     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21849     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
21850     {
21851 $check-mu-compute-offset-stmt:index-type-is-atom:
21852       (is-simple-mu-type? %edx 0)  # literal => eax
21853       3d/compare-eax-and 0/imm32/false
21854       75/jump-if-!= break/disp8
21855       (is-simple-mu-type? %edx 1)  # int => eax
21856       3d/compare-eax-and 0/imm32/false
21857       75/jump-if-!= break/disp8
21858       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
21859     }
21860     # - check for too many inouts
21861     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21862     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21863     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21864     3d/compare-eax-and 0/imm32/false
21865     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
21866     # - check for 0 outputs
21867     # var output/edi: (addr var) = stmt->outputs->value
21868     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21869     3d/compare-eax-and 0/imm32/false
21870     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
21871     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21872     89/<- %edi 0/r32/eax
21873     # - check output type
21874     # must have a non-atomic type
21875     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21876     89/<- %edx 0/r32/eax
21877     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
21878     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
21879     # type must start with (offset ...)
21880     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
21881     (is-simple-mu-type? %eax 7)  # offset => eax
21882     3d/compare-eax-and 0/imm32/false
21883     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
21884     # if tail(base-type) != tail(output-type) abort
21885     (type-tail %ebx)  # => eax
21886     89/<- %ebx 0/r32/eax
21887     (type-tail %edx)  # => eax
21888     (type-equal? %ebx %eax)  # => eax
21889     3d/compare-eax-and 0/imm32/false
21890     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
21891     # - check for too many outputs
21892     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21893     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21894     3d/compare-eax-and 0/imm32/false
21895     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
21896 $check-mu-compute-offset-stmt:end:
21897     # . restore registers
21898     5f/pop-to-edi
21899     5e/pop-to-esi
21900     5b/pop-to-ebx
21901     5a/pop-to-edx
21902     59/pop-to-ecx
21903     58/pop-to-eax
21904     # . epilogue
21905     89/<- %esp 5/r32/ebp
21906     5d/pop-to-ebp
21907     c3/return
21908 
21909 $check-mu-compute-offset-stmt:error-base-non-array-type:
21910     (write-buffered *(ebp+0x10) "fn ")
21911     8b/-> *(ebp+0xc) 0/r32/eax
21912     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21913     (write-buffered *(ebp+0x10) %eax)
21914     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
21915     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21916     (write-buffered *(ebp+0x10) %eax)
21917     (write-buffered *(ebp+0x10) "' is not an array\n")
21918     (flush *(ebp+0x10))
21919     (stop *(ebp+0x14) 1)
21920     # never gets here
21921 
21922 $check-mu-compute-offset-stmt:error-base-array-atom-type:
21923     (write-buffered *(ebp+0x10) "fn ")
21924     8b/-> *(ebp+0xc) 0/r32/eax
21925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21926     (write-buffered *(ebp+0x10) %eax)
21927     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
21928     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21929     (write-buffered *(ebp+0x10) %eax)
21930     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
21931     (flush *(ebp+0x10))
21932     (stop *(ebp+0x14) 1)
21933     # never gets here
21934 
21935 $check-mu-compute-offset-stmt:error-too-few-inouts:
21936     (write-buffered *(ebp+0x10) "fn ")
21937     8b/-> *(ebp+0xc) 0/r32/eax
21938     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21939     (write-buffered *(ebp+0x10) %eax)
21940     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
21941     (flush *(ebp+0x10))
21942     (stop *(ebp+0x14) 1)
21943     # never gets here
21944 
21945 $check-mu-compute-offset-stmt:error-invalid-index-type:
21946     (write-buffered *(ebp+0x10) "fn ")
21947     8b/-> *(ebp+0xc) 0/r32/eax
21948     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21949     (write-buffered *(ebp+0x10) %eax)
21950     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
21951     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21952     (write-buffered *(ebp+0x10) %eax)
21953     (write-buffered *(ebp+0x10) "' must be an int\n")
21954     (flush *(ebp+0x10))
21955     (stop *(ebp+0x14) 1)
21956     # never gets here
21957 
21958 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
21959     (write-buffered *(ebp+0x10) "fn ")
21960     8b/-> *(ebp+0xc) 0/r32/eax
21961     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21962     (write-buffered *(ebp+0x10) %eax)
21963     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
21964     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21965     (write-buffered *(ebp+0x10) %eax)
21966     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
21967     (flush *(ebp+0x10))
21968     (stop *(ebp+0x14) 1)
21969     # never gets here
21970 
21971 $check-mu-compute-offset-stmt:error-index-on-stack:
21972     (write-buffered *(ebp+0x10) "fn ")
21973     8b/-> *(ebp+0xc) 0/r32/eax
21974     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21975     (write-buffered *(ebp+0x10) %eax)
21976     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
21977     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21978     (write-buffered *(ebp+0x10) %eax)
21979     (write-buffered *(ebp+0x10) "' must be in a register\n")
21980     (flush *(ebp+0x10))
21981     (stop *(ebp+0x14) 1)
21982     # never gets here
21983 
21984 $check-mu-compute-offset-stmt:error-too-many-inouts:
21985     (write-buffered *(ebp+0x10) "fn ")
21986     8b/-> *(ebp+0xc) 0/r32/eax
21987     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21988     (write-buffered *(ebp+0x10) %eax)
21989     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
21990     (flush *(ebp+0x10))
21991     (stop *(ebp+0x14) 1)
21992     # never gets here
21993 
21994 $check-mu-compute-offset-stmt:error-too-few-outputs:
21995     (write-buffered *(ebp+0x10) "fn ")
21996     8b/-> *(ebp+0xc) 0/r32/eax
21997     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21998     (write-buffered *(ebp+0x10) %eax)
21999     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
22000     (flush *(ebp+0x10))
22001     (stop *(ebp+0x14) 1)
22002     # never gets here
22003 
22004 $check-mu-compute-offset-stmt:error-too-many-outputs:
22005     (write-buffered *(ebp+0x10) "fn ")
22006     8b/-> *(ebp+0xc) 0/r32/eax
22007     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22008     (write-buffered *(ebp+0x10) %eax)
22009     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
22010     (flush *(ebp+0x10))
22011     (stop *(ebp+0x14) 1)
22012     # never gets here
22013 
22014 $check-mu-compute-offset-stmt:error-output-not-in-register:
22015     (write-buffered *(ebp+0x10) "fn ")
22016     8b/-> *(ebp+0xc) 0/r32/eax
22017     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22018     (write-buffered *(ebp+0x10) %eax)
22019     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22020     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22021     (write-buffered *(ebp+0x10) %eax)
22022     (write-buffered *(ebp+0x10) "' is not in a register\n")
22023     (flush *(ebp+0x10))
22024     (stop *(ebp+0x14) 1)
22025     # never gets here
22026 
22027 $check-mu-compute-offset-stmt:error-output-type-not-offset:
22028     (write-buffered *(ebp+0x10) "fn ")
22029     8b/-> *(ebp+0xc) 0/r32/eax
22030     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22031     (write-buffered *(ebp+0x10) %eax)
22032     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22033     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22034     (write-buffered *(ebp+0x10) %eax)
22035     (write-buffered *(ebp+0x10) "' must be an offset\n")
22036     (flush *(ebp+0x10))
22037     (stop *(ebp+0x14) 1)
22038     # never gets here
22039 
22040 $check-mu-compute-offset-stmt:error-bad-output-type:
22041     (write-buffered *(ebp+0x10) "fn ")
22042     8b/-> *(ebp+0xc) 0/r32/eax
22043     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22044     (write-buffered *(ebp+0x10) %eax)
22045     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22046     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22047     (write-buffered *(ebp+0x10) %eax)
22048     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22049     (flush *(ebp+0x10))
22050     (stop *(ebp+0x14) 1)
22051     # never gets here
22052 
22053 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22054     # . prologue
22055     55/push-ebp
22056     89/<- %ebp 4/r32/esp
22057     # . save registers
22058     50/push-eax
22059     51/push-ecx
22060     53/push-ebx
22061     56/push-esi
22062     57/push-edi
22063     # esi = stmt
22064     8b/-> *(ebp+8) 6/r32/esi
22065 $check-mu-copy-object-stmt:check-for-output:
22066     # if stmt->outputs abort
22067     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22068     3d/compare-eax-and 0/imm32
22069     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
22070 $check-mu-copy-object-stmt:get-left:
22071     # var dest/edi: (addr stmt-var) = stmt->inouts
22072     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22073     89/<- %edi 0/r32/eax
22074     # zero inouts
22075     3d/compare-eax-and 0/imm32
22076     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22077 $check-mu-copy-object-stmt:get-src:
22078     # var src/esi: (addr stmt-var) = dest->next
22079     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22080     89/<- %esi 0/r32/eax
22081     # 1 inout
22082     3d/compare-eax-and 0/imm32
22083     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22084     # > 2 inouts
22085     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22086     3d/compare-eax-and 0/imm32
22087     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22088 $check-mu-copy-object-stmt:types:
22089     # var src-type/ecx: (addr type-tree) = src->value->type
22090     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22091     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22092     89/<- %ecx 0/r32/eax
22093     # if (src->is-deref?) src-type = src-type->payload
22094     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22095     3d/compare-eax-and 0/imm32/false
22096     {
22097       74/jump-if-= break/disp8
22098       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22099       # if src-type->right is null, src-type = src-type->left
22100       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22101       {
22102         75/jump-if-!= break/disp8
22103         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22104       }
22105       89/<- %ecx 0/r32/eax
22106     }
22107     # if src-type is not addr, abort
22108     (is-mu-addr-type? %ecx)  # => eax
22109     3d/compare-eax-and 0/imm32/false
22110     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
22111     # var dest-type/ebx: (addr type-tree) = dest->value->type
22112     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22113     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22114     89/<- %ebx 0/r32/eax
22115     # if (dest->is-deref?) dest-type = dest-type->payload
22116     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22117     3d/compare-eax-and 0/imm32/false
22118     {
22119       74/jump-if-= break/disp8
22120       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22121       # if dest-type->right is null, dest-type = dest-type->left
22122       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22123       {
22124         75/jump-if-!= break/disp8
22125         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22126       }
22127       89/<- %ebx 0/r32/eax
22128     }
22129     # if (dest-type != src-type) abort
22130     (type-equal? %ecx %ebx)  # => eax
22131     3d/compare-eax-and 0/imm32
22132     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
22133 $check-mu-copy-object-stmt:end:
22134     # . restore registers
22135     5f/pop-to-edi
22136     5e/pop-to-esi
22137     5b/pop-to-ebx
22138     59/pop-to-ecx
22139     58/pop-to-eax
22140     # . epilogue
22141     89/<- %esp 5/r32/ebp
22142     5d/pop-to-ebp
22143     c3/return
22144 
22145 $check-mu-copy-object-stmt:error-incorrect-inouts:
22146     (write-buffered *(ebp+0x10) "fn ")
22147     8b/-> *(ebp+0xc) 0/r32/eax
22148     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22149     (write-buffered *(ebp+0x10) %eax)
22150     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
22151     (flush *(ebp+0x10))
22152     (stop *(ebp+0x14) 1)
22153     # never gets here
22154 
22155 $check-mu-copy-object-stmt:error-too-many-outputs:
22156     (write-buffered *(ebp+0x10) "fn ")
22157     8b/-> *(ebp+0xc) 0/r32/eax
22158     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22159     (write-buffered *(ebp+0x10) %eax)
22160     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
22161     (flush *(ebp+0x10))
22162     (stop *(ebp+0x14) 1)
22163     # never gets here
22164 
22165 $check-mu-copy-object-stmt:error-invalid-types:
22166     (write-buffered *(ebp+0x10) "fn ")
22167     8b/-> *(ebp+0xc) 0/r32/eax
22168     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22169     (write-buffered *(ebp+0x10) %eax)
22170     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
22171     (flush *(ebp+0x10))
22172     (stop *(ebp+0x14) 1)
22173     # never gets here
22174 
22175 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22176     # . prologue
22177     55/push-ebp
22178     89/<- %ebp 4/r32/esp
22179     # . save registers
22180     50/push-eax
22181     53/push-ebx
22182     56/push-esi
22183     57/push-edi
22184     # esi = stmt
22185     8b/-> *(ebp+8) 6/r32/esi
22186 $check-mu-allocate-stmt:check-for-output:
22187     # if stmt->outputs abort
22188     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22189     3d/compare-eax-and 0/imm32
22190     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
22191 $check-mu-allocate-stmt:get-target:
22192     # var target/edi: (addr stmt-var) = stmt->inouts
22193     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22194     89/<- %edi 0/r32/eax
22195     # zero inouts
22196     3d/compare-eax-and 0/imm32
22197     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
22198     # > 1 inouts
22199     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22200     3d/compare-eax-and 0/imm32
22201     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
22202 $check-mu-allocate-stmt:check-type:
22203     # var target-type/ebx: (addr type-tree) = target->value->type
22204     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22205     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22206     89/<- %ebx 0/r32/eax
22207     # if (target->is-deref?) target-type = target-type->payload
22208     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22209     3d/compare-eax-and 0/imm32/false
22210     {
22211       74/jump-if-= break/disp8
22212       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22213       # if target-type->right is null, target-type = target-type->left
22214       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22215       {
22216         75/jump-if-!= break/disp8
22217         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22218       }
22219       89/<- %ebx 0/r32/eax
22220     }
22221     # if target-type is not addr, abort
22222     (is-mu-addr-type? %ebx)  # => eax
22223     3d/compare-eax-and 0/imm32/false
22224     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
22225     # if target-type->right is an atom, abort
22226     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22227     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22228     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
22229     # if target-type->right->left is not handle, abort
22230     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22231     (is-simple-mu-type? %eax 4)  # handle => eax
22232     3d/compare-eax-and 0/imm32/false
22233     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
22234 $check-mu-allocate-stmt:end:
22235     # . restore registers
22236     5f/pop-to-edi
22237     5e/pop-to-esi
22238     5b/pop-to-ebx
22239     58/pop-to-eax
22240     # . epilogue
22241     89/<- %esp 5/r32/ebp
22242     5d/pop-to-ebp
22243     c3/return
22244 
22245 $check-mu-allocate-stmt:error-incorrect-inouts:
22246     (write-buffered *(ebp+0x10) "fn ")
22247     8b/-> *(ebp+0xc) 0/r32/eax
22248     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22249     (write-buffered *(ebp+0x10) %eax)
22250     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
22251     (flush *(ebp+0x10))
22252     (stop *(ebp+0x14) 1)
22253     # never gets here
22254 
22255 $check-mu-allocate-stmt:error-too-many-outputs:
22256     (write-buffered *(ebp+0x10) "fn ")
22257     8b/-> *(ebp+0xc) 0/r32/eax
22258     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22259     (write-buffered *(ebp+0x10) %eax)
22260     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
22261     (flush *(ebp+0x10))
22262     (stop *(ebp+0x14) 1)
22263     # never gets here
22264 
22265 $check-mu-allocate-stmt:error-invalid-type:
22266     (write-buffered *(ebp+0x10) "fn ")
22267     8b/-> *(ebp+0xc) 0/r32/eax
22268     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22269     (write-buffered *(ebp+0x10) %eax)
22270     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
22271     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22272     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22273     (write-buffered *(ebp+0x10) %eax)
22274     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
22275     (flush *(ebp+0x10))
22276     (stop *(ebp+0x14) 1)
22277     # never gets here
22278 
22279 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22280     # . prologue
22281     55/push-ebp
22282     89/<- %ebp 4/r32/esp
22283     # . save registers
22284     50/push-eax
22285     53/push-ebx
22286     56/push-esi
22287     57/push-edi
22288     # esi = stmt
22289     8b/-> *(ebp+8) 6/r32/esi
22290 $check-mu-populate-stmt:check-for-output:
22291     # if stmt->outputs abort
22292     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22293     3d/compare-eax-and 0/imm32
22294     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
22295 $check-mu-populate-stmt:get-target:
22296     # var target/edi: (addr stmt-var) = stmt->inouts
22297     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22298     89/<- %edi 0/r32/eax
22299     # zero inouts
22300     3d/compare-eax-and 0/imm32
22301     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
22302 $check-mu-populate-stmt:get-length:
22303     # var length/esi: (addr stmt-var) = dest->next
22304     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22305     89/<- %esi 0/r32/eax
22306     # 1 inout
22307     3d/compare-eax-and 0/imm32
22308     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22309     # > 2 inouts
22310     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22311     3d/compare-eax-and 0/imm32
22312     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
22313 $check-mu-populate-stmt:check-target-type:
22314     # var target-type/ebx: (addr type-tree) = target->value->type
22315     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22316     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22317     89/<- %ebx 0/r32/eax
22318 $check-mu-populate-stmt:check-target-type-deref:
22319     # if (target->is-deref?) target-type = target-type->payload
22320     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22321     3d/compare-eax-and 0/imm32/false
22322     {
22323       74/jump-if-= break/disp8
22324       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22325       # if target-type->right is null, target-type = target-type->left
22326       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22327       {
22328         75/jump-if-!= break/disp8
22329         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22330       }
22331       89/<- %ebx 0/r32/eax
22332     }
22333 $check-mu-populate-stmt:check-target-type-addr:
22334     # if target-type is not addr, abort
22335     (is-mu-addr-type? %ebx)  # => eax
22336     3d/compare-eax-and 0/imm32/false
22337     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
22338     # if target-type->right is an atom, abort
22339     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22340     89/<- %ebx 0/r32/eax
22341     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22342     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
22343 $check-mu-populate-stmt:check-target-type-handle:
22344     # if target-type->right->left is not handle, abort
22345     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22346     (is-simple-mu-type? %eax 4)  # handle => eax
22347     3d/compare-eax-and 0/imm32/false
22348     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
22349     # if target-type->right->right is an atom, abort
22350     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22351     89/<- %ebx 0/r32/eax
22352     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22353     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
22354 $check-mu-populate-stmt:check-target-type-array:
22355     # if target-type->right->right->left is not array, abort
22356     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22357     (is-simple-mu-type? %eax 3)  # array => eax
22358     3d/compare-eax-and 0/imm32/false
22359     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
22360 $check-mu-populate-stmt:check-length-type:
22361     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22362     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22363     89/<- %ebx 0/r32/eax
22364     (is-simple-mu-type? %ebx 0)  # literal => eax
22365     3d/compare-eax-and 0/imm32/false
22366     75/jump-if-!= $check-mu-populate-stmt:end/disp8
22367     (is-simple-mu-type? %ebx 1)  # int => eax
22368     3d/compare-eax-and 0/imm32/false
22369     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
22370 $check-mu-populate-stmt:end:
22371     # . restore registers
22372     5f/pop-to-edi
22373     5e/pop-to-esi
22374     5b/pop-to-ebx
22375     58/pop-to-eax
22376     # . epilogue
22377     89/<- %esp 5/r32/ebp
22378     5d/pop-to-ebp
22379     c3/return
22380 
22381 $check-mu-populate-stmt:error-incorrect-inouts:
22382     (write-buffered *(ebp+0x10) "fn ")
22383     8b/-> *(ebp+0xc) 0/r32/eax
22384     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22385     (write-buffered *(ebp+0x10) %eax)
22386     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
22387     (flush *(ebp+0x10))
22388     (stop *(ebp+0x14) 1)
22389     # never gets here
22390 
22391 $check-mu-populate-stmt:error-too-many-outputs:
22392     (write-buffered *(ebp+0x10) "fn ")
22393     8b/-> *(ebp+0xc) 0/r32/eax
22394     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22395     (write-buffered *(ebp+0x10) %eax)
22396     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
22397     (flush *(ebp+0x10))
22398     (stop *(ebp+0x14) 1)
22399     # never gets here
22400 
22401 $check-mu-populate-stmt:error-invalid-target-type:
22402     (write-buffered *(ebp+0x10) "fn ")
22403     8b/-> *(ebp+0xc) 0/r32/eax
22404     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22405     (write-buffered *(ebp+0x10) %eax)
22406     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
22407     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22408     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22409     (write-buffered *(ebp+0x10) %eax)
22410     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
22411     (flush *(ebp+0x10))
22412     (stop *(ebp+0x14) 1)
22413     # never gets here
22414 
22415 $check-mu-populate-stmt:error-invalid-length-type:
22416     (write-buffered *(ebp+0x10) "fn ")
22417     8b/-> *(ebp+0xc) 0/r32/eax
22418     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22419     (write-buffered *(ebp+0x10) %eax)
22420     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
22421     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22422     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22423     (write-buffered *(ebp+0x10) %eax)
22424     (write-buffered *(ebp+0x10) "' must be an int\n")
22425     (flush *(ebp+0x10))
22426     (stop *(ebp+0x14) 1)
22427     # never gets here
22428 
22429 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22430     # . prologue
22431     55/push-ebp
22432     89/<- %ebp 4/r32/esp
22433     # . save registers
22434     50/push-eax
22435     53/push-ebx
22436     56/push-esi
22437     57/push-edi
22438     # esi = stmt
22439     8b/-> *(ebp+8) 6/r32/esi
22440 $check-mu-populate-stream-stmt:check-for-output:
22441     # if stmt->outputs abort
22442     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22443     3d/compare-eax-and 0/imm32
22444     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
22445 $check-mu-populate-stream-stmt:get-target:
22446     # var target/edi: (addr stmt-var) = stmt->inouts
22447     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22448     89/<- %edi 0/r32/eax
22449     # zero inouts
22450     3d/compare-eax-and 0/imm32
22451     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
22452 $check-mu-populate-stream-stmt:get-length:
22453     # var length/esi: (addr stmt-var) = dest->next
22454     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22455     89/<- %esi 0/r32/eax
22456     # 1 inout
22457     3d/compare-eax-and 0/imm32
22458     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22459     # > 2 inouts
22460     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22461     3d/compare-eax-and 0/imm32
22462     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
22463 $check-mu-populate-stream-stmt:check-target-type:
22464     # var target-type/ebx: (addr type-tree) = target->value->type
22465     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22466     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22467     89/<- %ebx 0/r32/eax
22468 $check-mu-populate-stream-stmt:check-target-type-deref:
22469     # if (target->is-deref?) target-type = target-type->payload
22470     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22471     3d/compare-eax-and 0/imm32/false
22472     {
22473       74/jump-if-= break/disp8
22474       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22475       # if target-type->right is null, target-type = target-type->left
22476       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22477       {
22478         75/jump-if-!= break/disp8
22479         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22480       }
22481       89/<- %ebx 0/r32/eax
22482     }
22483 $check-mu-populate-stream-stmt:check-target-type-addr:
22484     # if target-type is not addr, abort
22485     (is-mu-addr-type? %ebx)  # => eax
22486     3d/compare-eax-and 0/imm32/false
22487     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
22488     # if target-type->right is an atom, abort
22489     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22490     89/<- %ebx 0/r32/eax
22491     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22492     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
22493 $check-mu-populate-stream-stmt:check-target-type-handle:
22494     # if target-type->right->left is not handle, abort
22495     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22496     (is-simple-mu-type? %eax 4)  # handle => eax
22497     3d/compare-eax-and 0/imm32/false
22498     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
22499     # if target-type->right->right is an atom, abort
22500     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22501     89/<- %ebx 0/r32/eax
22502     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22503     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
22504 $check-mu-populate-stream-stmt:check-target-type-stream:
22505     # if target-type->right->right->left is not stream, abort
22506     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22507     (is-simple-mu-type? %eax 0xb)  # stream => eax
22508     3d/compare-eax-and 0/imm32/false
22509     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
22510 $check-mu-populate-stream-stmt:check-length-type:
22511     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22512     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22513     89/<- %ebx 0/r32/eax
22514     (is-simple-mu-type? %ebx 0)  # literal => eax
22515     3d/compare-eax-and 0/imm32/false
22516     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
22517     (is-simple-mu-type? %ebx 1)  # int => eax
22518     3d/compare-eax-and 0/imm32/false
22519     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
22520 $check-mu-populate-stream-stmt:end:
22521     # . restore registers
22522     5f/pop-to-edi
22523     5e/pop-to-esi
22524     5b/pop-to-ebx
22525     58/pop-to-eax
22526     # . epilogue
22527     89/<- %esp 5/r32/ebp
22528     5d/pop-to-ebp
22529     c3/return
22530 
22531 $check-mu-populate-stream-stmt:error-incorrect-inouts:
22532     (write-buffered *(ebp+0x10) "fn ")
22533     8b/-> *(ebp+0xc) 0/r32/eax
22534     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22535     (write-buffered *(ebp+0x10) %eax)
22536     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
22537     (flush *(ebp+0x10))
22538     (stop *(ebp+0x14) 1)
22539     # never gets here
22540 
22541 $check-mu-populate-stream-stmt:error-too-many-outputs:
22542     (write-buffered *(ebp+0x10) "fn ")
22543     8b/-> *(ebp+0xc) 0/r32/eax
22544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22545     (write-buffered *(ebp+0x10) %eax)
22546     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
22547     (flush *(ebp+0x10))
22548     (stop *(ebp+0x14) 1)
22549     # never gets here
22550 
22551 $check-mu-populate-stream-stmt:error-invalid-target-type:
22552     (write-buffered *(ebp+0x10) "fn ")
22553     8b/-> *(ebp+0xc) 0/r32/eax
22554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22555     (write-buffered *(ebp+0x10) %eax)
22556     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
22557     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22558     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22559     (write-buffered *(ebp+0x10) %eax)
22560     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
22561     (flush *(ebp+0x10))
22562     (stop *(ebp+0x14) 1)
22563     # never gets here
22564 
22565 $check-mu-populate-stream-stmt:error-invalid-length-type:
22566     (write-buffered *(ebp+0x10) "fn ")
22567     8b/-> *(ebp+0xc) 0/r32/eax
22568     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22569     (write-buffered *(ebp+0x10) %eax)
22570     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
22571     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22572     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22573     (write-buffered *(ebp+0x10) %eax)
22574     (write-buffered *(ebp+0x10) "' must be an int\n")
22575     (flush *(ebp+0x10))
22576     (stop *(ebp+0x14) 1)
22577     # never gets here
22578 
22579 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22580     # . prologue
22581     55/push-ebp
22582     89/<- %ebp 4/r32/esp
22583     # . save registers
22584     50/push-eax
22585     51/push-ecx
22586     52/push-edx
22587     53/push-ebx
22588     56/push-esi
22589     57/push-edi
22590     # esi = stmt
22591     8b/-> *(ebp+8) 6/r32/esi
22592     # - check for 0 inouts
22593     # var base/ecx: (addr var) = stmt->inouts->value
22594     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22595 $check-mu-read-from-stream-stmt:check-no-inouts:
22596     3d/compare-eax-and 0/imm32
22597     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
22598     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22599     89/<- %ecx 0/r32/eax
22600     # - check base type is (addr stream T)
22601     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22602     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22603     89/<- %ebx 0/r32/eax
22604 $check-mu-read-from-stream-stmt:check-base-is-compound:
22605     # if base-type is an atom, abort
22606     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22607     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
22608 $check-mu-read-from-stream-stmt:check-base-is-addr:
22609     # if type->left not addr, abort
22610     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22611     (is-simple-mu-type? %eax 2)  # addr => eax
22612     3d/compare-eax-and 0/imm32/false
22613     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
22614 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
22615     # base-type = base-type->right
22616     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22617     89/<- %ebx 0/r32/eax
22618     # ensure base-type->left == stream
22619     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22620     (is-simple-mu-type? %eax 0xb)  # stream => eax
22621     3d/compare-eax-and 0/imm32/false
22622     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
22623     # - check target type is (addr T)
22624     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
22625     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22626     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22627 $check-mu-read-from-stream-stmt:check-single-inout:
22628     3d/compare-eax-and 0/imm32
22629     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
22630     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22631     89/<- %ecx 0/r32/eax
22632     # var target-type/edx: (addr type-tree)
22633     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22634     89/<- %edx 0/r32/eax
22635     # if target-type is an atom, it must be a literal or int
22636 $check-mu-read-from-stream-stmt:check-target-is-compound:
22637     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22638     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
22639 $check-mu-read-from-stream-stmt:check-target-type:
22640     # target type must start with (addr ...)
22641     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22642     (is-simple-mu-type? %eax 2)  # addr => eax
22643     3d/compare-eax-and 0/imm32/false
22644     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
22645     # if tail(base-type) != tail(target-type) abort
22646     (type-tail %ebx)  # => eax
22647     89/<- %ebx 0/r32/eax
22648     (type-tail %edx)  # => eax
22649     (type-equal? %ebx %eax)  # => eax
22650     3d/compare-eax-and 0/imm32/false
22651     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
22652 $check-mu-read-from-stream-stmt:check-too-many-inouts:
22653     # - check for too many inouts
22654     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22655     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22656     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22657     3d/compare-eax-and 0/imm32/false
22658     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
22659 $check-mu-read-from-stream-stmt:check-unexpected-output:
22660     # - check for any output
22661     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22662     3d/compare-eax-and 0/imm32/false
22663     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
22664 $check-mu-read-from-stream-stmt:end:
22665     # . restore registers
22666     5f/pop-to-edi
22667     5e/pop-to-esi
22668     5b/pop-to-ebx
22669     5a/pop-to-edx
22670     59/pop-to-ecx
22671     58/pop-to-eax
22672     # . epilogue
22673     89/<- %esp 5/r32/ebp
22674     5d/pop-to-ebp
22675     c3/return
22676 
22677 $check-mu-read-from-stream-stmt:error-invalid-base-type:
22678     (write-buffered *(ebp+0x10) "fn ")
22679     8b/-> *(ebp+0xc) 0/r32/eax
22680     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22681     (write-buffered *(ebp+0x10) %eax)
22682     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
22683     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22684     (write-buffered *(ebp+0x10) %eax)
22685     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
22686     (flush *(ebp+0x10))
22687     (stop *(ebp+0x14) 1)
22688     # never gets here
22689 
22690 $check-mu-read-from-stream-stmt:error-too-few-inouts:
22691     (write-buffered *(ebp+0x10) "fn ")
22692     8b/-> *(ebp+0xc) 0/r32/eax
22693     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22694     (write-buffered *(ebp+0x10) %eax)
22695     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
22696     (flush *(ebp+0x10))
22697     (stop *(ebp+0x14) 1)
22698     # never gets here
22699 
22700 $check-mu-read-from-stream-stmt:error-target-type-not-address:
22701     (write-buffered *(ebp+0x10) "fn ")
22702     8b/-> *(ebp+0xc) 0/r32/eax
22703     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22704     (write-buffered *(ebp+0x10) %eax)
22705     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
22706     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22707     (write-buffered *(ebp+0x10) %eax)
22708     (write-buffered *(ebp+0x10) "' must be an addr\n")
22709     (flush *(ebp+0x10))
22710     (stop *(ebp+0x14) 1)
22711     # never gets here
22712 
22713 $check-mu-read-from-stream-stmt:error-invalid-target-type:
22714     (write-buffered *(ebp+0x10) "fn ")
22715     8b/-> *(ebp+0xc) 0/r32/eax
22716     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22717     (write-buffered *(ebp+0x10) %eax)
22718     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
22719     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22720     (write-buffered *(ebp+0x10) %eax)
22721     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22722     (flush *(ebp+0x10))
22723     (stop *(ebp+0x14) 1)
22724     # never gets here
22725 
22726 $check-mu-read-from-stream-stmt:error-too-many-inouts:
22727     (write-buffered *(ebp+0x10) "fn ")
22728     8b/-> *(ebp+0xc) 0/r32/eax
22729     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22730     (write-buffered *(ebp+0x10) %eax)
22731     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
22732     (flush *(ebp+0x10))
22733     (stop *(ebp+0x14) 1)
22734     # never gets here
22735 
22736 $check-mu-read-from-stream-stmt:error-unexpected-output:
22737     (write-buffered *(ebp+0x10) "fn ")
22738     8b/-> *(ebp+0xc) 0/r32/eax
22739     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22740     (write-buffered *(ebp+0x10) %eax)
22741     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
22742     (flush *(ebp+0x10))
22743     (stop *(ebp+0x14) 1)
22744     # never gets here
22745 
22746 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22747     # . prologue
22748     55/push-ebp
22749     89/<- %ebp 4/r32/esp
22750     # . save registers
22751     50/push-eax
22752     51/push-ecx
22753     52/push-edx
22754     53/push-ebx
22755     56/push-esi
22756     57/push-edi
22757     # esi = stmt
22758     8b/-> *(ebp+8) 6/r32/esi
22759     # - check for 0 inouts
22760     # var base/ecx: (addr var) = stmt->inouts->value
22761     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22762 $check-mu-write-to-stream-stmt:check-no-inouts:
22763     3d/compare-eax-and 0/imm32
22764     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
22765     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22766     89/<- %ecx 0/r32/eax
22767     # - check base type is (addr stream T)
22768     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22769     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22770     89/<- %ebx 0/r32/eax
22771 $check-mu-write-to-stream-stmt:check-base-is-compound:
22772     # if base-type is an atom, abort
22773     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22774     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
22775 $check-mu-write-to-stream-stmt:check-base-is-addr:
22776     # if type->left not addr, abort
22777     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22778     (is-simple-mu-type? %eax 2)  # addr => eax
22779     3d/compare-eax-and 0/imm32/false
22780     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
22781 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
22782     # base-type = base-type->right
22783     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22784     89/<- %ebx 0/r32/eax
22785     # ensure base-type->left == stream
22786     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22787     (is-simple-mu-type? %eax 0xb)  # stream => eax
22788     3d/compare-eax-and 0/imm32/false
22789     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
22790     # - check target type is (addr T)
22791     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
22792     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22793     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22794 $check-mu-write-to-stream-stmt:check-single-inout:
22795     3d/compare-eax-and 0/imm32
22796     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
22797     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22798     89/<- %ecx 0/r32/eax
22799     # var target-type/edx: (addr type-tree)
22800     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22801     89/<- %edx 0/r32/eax
22802     # if target-type is an atom, it must be a literal or int
22803 $check-mu-write-to-stream-stmt:check-target-is-compound:
22804     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22805     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
22806 $check-mu-write-to-stream-stmt:check-target-type:
22807     # target type must start with (addr ...)
22808     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22809     (is-simple-mu-type? %eax 2)  # addr => eax
22810     3d/compare-eax-and 0/imm32/false
22811     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
22812     # if tail(base-type) != tail(target-type) abort
22813     (type-tail %ebx)  # => eax
22814     89/<- %ebx 0/r32/eax
22815     (type-tail %edx)  # => eax
22816     (type-equal? %ebx %eax)  # => eax
22817     3d/compare-eax-and 0/imm32/false
22818     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
22819 $check-mu-write-to-stream-stmt:check-too-many-inouts:
22820     # - check for too many inouts
22821     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22822     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22823     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22824     3d/compare-eax-and 0/imm32/false
22825     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
22826 $check-mu-write-to-stream-stmt:check-unexpected-output:
22827     # - check for any output
22828     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22829     3d/compare-eax-and 0/imm32/false
22830     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
22831 $check-mu-write-to-stream-stmt:end:
22832     # . restore registers
22833     5f/pop-to-edi
22834     5e/pop-to-esi
22835     5b/pop-to-ebx
22836     5a/pop-to-edx
22837     59/pop-to-ecx
22838     58/pop-to-eax
22839     # . epilogue
22840     89/<- %esp 5/r32/ebp
22841     5d/pop-to-ebp
22842     c3/return
22843 
22844 $check-mu-write-to-stream-stmt:error-invalid-base-type:
22845     (write-buffered *(ebp+0x10) "fn ")
22846     8b/-> *(ebp+0xc) 0/r32/eax
22847     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22848     (write-buffered *(ebp+0x10) %eax)
22849     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
22850     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22851     (write-buffered *(ebp+0x10) %eax)
22852     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
22853     (flush *(ebp+0x10))
22854     (stop *(ebp+0x14) 1)
22855     # never gets here
22856 
22857 $check-mu-write-to-stream-stmt:error-too-few-inouts:
22858     (write-buffered *(ebp+0x10) "fn ")
22859     8b/-> *(ebp+0xc) 0/r32/eax
22860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22861     (write-buffered *(ebp+0x10) %eax)
22862     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
22863     (flush *(ebp+0x10))
22864     (stop *(ebp+0x14) 1)
22865     # never gets here
22866 
22867 $check-mu-write-to-stream-stmt:error-target-type-not-address:
22868     (write-buffered *(ebp+0x10) "fn ")
22869     8b/-> *(ebp+0xc) 0/r32/eax
22870     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22871     (write-buffered *(ebp+0x10) %eax)
22872     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
22873     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22874     (write-buffered *(ebp+0x10) %eax)
22875     (write-buffered *(ebp+0x10) "' must be an addr\n")
22876     (flush *(ebp+0x10))
22877     (stop *(ebp+0x14) 1)
22878     # never gets here
22879 
22880 $check-mu-write-to-stream-stmt:error-invalid-target-type:
22881     (write-buffered *(ebp+0x10) "fn ")
22882     8b/-> *(ebp+0xc) 0/r32/eax
22883     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22884     (write-buffered *(ebp+0x10) %eax)
22885     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
22886     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22887     (write-buffered *(ebp+0x10) %eax)
22888     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22889     (flush *(ebp+0x10))
22890     (stop *(ebp+0x14) 1)
22891     # never gets here
22892 
22893 $check-mu-write-to-stream-stmt:error-too-many-inouts:
22894     (write-buffered *(ebp+0x10) "fn ")
22895     8b/-> *(ebp+0xc) 0/r32/eax
22896     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22897     (write-buffered *(ebp+0x10) %eax)
22898     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
22899     (flush *(ebp+0x10))
22900     (stop *(ebp+0x14) 1)
22901     # never gets here
22902 
22903 $check-mu-write-to-stream-stmt:error-unexpected-output:
22904     (write-buffered *(ebp+0x10) "fn ")
22905     8b/-> *(ebp+0xc) 0/r32/eax
22906     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22907     (write-buffered *(ebp+0x10) %eax)
22908     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
22909     (flush *(ebp+0x10))
22910     (stop *(ebp+0x14) 1)
22911     # never gets here
22912 
22913 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22914     # . prologue
22915     55/push-ebp
22916     89/<- %ebp 4/r32/esp
22917     # . save registers
22918 $check-mu-convert-stmt:end:
22919     # . restore registers
22920     # . epilogue
22921     89/<- %esp 5/r32/ebp
22922     5d/pop-to-ebp
22923     c3/return
22924 
22925 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22926     # . prologue
22927     55/push-ebp
22928     89/<- %ebp 4/r32/esp
22929     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
22930     68/push 0/imm32
22931     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
22932     81 5/subop/subtract %esp 0x60/imm32
22933     68/push 0x60/imm32/size
22934     68/push 0/imm32/read
22935     68/push 0/imm32/write
22936     # save a pointer to type-parameters-storage at type-parameters
22937     89/<- *(ebp-4) 4/r32/esp
22938     (clear-stream *(ebp-4))
22939     # . save registers
22940     50/push-eax
22941     51/push-ecx
22942     52/push-edx
22943     53/push-ebx
22944     56/push-esi
22945     57/push-edi
22946     # esi = stmt
22947     8b/-> *(ebp+8) 6/r32/esi
22948     # edi = callee
22949     8b/-> *(ebp+0xc) 7/r32/edi
22950     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
22951     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22952     89/<- %ecx 0/r32/eax
22953     # var expected/edx: (addr list var) = lookup(f->inouts)
22954     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
22955     89/<- %edx 0/r32/eax
22956     {
22957 $check-mu-call:check-for-inouts:
22958       # if (inouts == 0) break
22959       81 7/subop/compare %ecx 0/imm32
22960       0f 84/jump-if-= break/disp32
22961       # if (expected == 0) error
22962       81 7/subop/compare %edx 0/imm32
22963       0f 84/jump-if-= break/disp32
22964 $check-mu-call:check-null-addr:
22965       # if (inouts->value->name == "0") continue
22966       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22967       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22968       (string-equal? %eax "0")  # => eax
22969       3d/compare-eax-and 0/imm32/false
22970       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
22971 $check-mu-call:check-inout-type:
22972       # var t/ebx: (addr type-tree) = inouts->value->type
22973       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22974       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22975       89/<- %ebx 0/r32/eax
22976       # if (inouts->is-deref?) t = t->right
22977       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
22978       {
22979         74/jump-if-= break/disp8
22980         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22981         89/<- %ebx 0/r32/eax
22982         # if t->right is null, t = t->left
22983         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
22984         75/jump-if-!= break/disp8
22985         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22986         89/<- %ebx 0/r32/eax
22987       }
22988       # var v2/eax: (addr v) = lookup(expected->value)
22989       (lookup *edx *(edx+4))  # List-value List-value => eax
22990       # var t2/eax: (addr type-tree) = lookup(v2->type)
22991       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22992       # if (t != t2) error
22993       (type-match? %eax %ebx *(ebp-4))  # => eax
22994       3d/compare-eax-and 0/imm32/false
22995       {
22996         0f 85/jump-if-!= break/disp32
22997         (write-buffered *(ebp+0x14) "fn ")
22998         8b/-> *(ebp+0x10) 0/r32/eax
22999         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23000         (write-buffered *(ebp+0x14) %eax)
23001         (write-buffered *(ebp+0x14) ": call ")
23002         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23003         (write-buffered *(ebp+0x14) %eax)
23004         (write-buffered *(ebp+0x14) ": type for inout '")
23005         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23006         (lookup *eax *(eax+4))  # Var-name Var-name => eax
23007         (write-buffered *(ebp+0x14) %eax)
23008         (write-buffered *(ebp+0x14) "' is not right\n")
23009         (flush *(ebp+0x14))
23010         (stop *(ebp+0x18) 1)
23011       }
23012 $check-mu-call:continue-to-next-inout:
23013       # inouts = lookup(inouts->next)
23014       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
23015       89/<- %ecx 0/r32/eax
23016       # expected = lookup(expected->next)
23017       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
23018       89/<- %edx 0/r32/eax
23019       #
23020       e9/jump loop/disp32
23021     }
23022 $check-mu-call:check-inout-count:
23023     # if (inouts == expected) proceed
23024     39/compare %ecx 2/r32/edx
23025     {
23026       0f 84/jump-if-= break/disp32
23027       # exactly one of the two is null
23028       # if (inouts == 0) error("too many inouts")
23029       {
23030         81 7/subop/compare %ecx 0/imm32
23031         0f 84/jump-if-= break/disp32
23032         (write-buffered *(ebp+0x14) "fn ")
23033         8b/-> *(ebp+0x10) 0/r32/eax
23034         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23035         (write-buffered *(ebp+0x14) %eax)
23036         (write-buffered *(ebp+0x14) ": call ")
23037         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23038         (write-buffered *(ebp+0x14) %eax)
23039         (write-buffered *(ebp+0x14) ": too many inouts\n")
23040         (flush *(ebp+0x14))
23041         (stop *(ebp+0x18) 1)
23042       }
23043       # if (expected == 0) error("too few inouts")
23044       {
23045         81 7/subop/compare %edx 0/imm32
23046         0f 84/jump-if-= break/disp32
23047         (write-buffered *(ebp+0x14) "fn ")
23048         8b/-> *(ebp+0x10) 0/r32/eax
23049         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23050         (write-buffered *(ebp+0x14) %eax)
23051         (write-buffered *(ebp+0x14) ": call ")
23052         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23053         (write-buffered *(ebp+0x14) %eax)
23054         (write-buffered *(ebp+0x14) ": too few inouts\n")
23055         (flush *(ebp+0x14))
23056         (stop *(ebp+0x18) 1)
23057       }
23058     }
23059 $check-mu-call:check-outputs:
23060     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
23061     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23062     89/<- %ecx 0/r32/eax
23063     # var expected/edx: (addr list var) = lookup(f->outputs)
23064     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
23065     89/<- %edx 0/r32/eax
23066     {
23067 $check-mu-call:check-for-outputs:
23068       # if (outputs == 0) break
23069       81 7/subop/compare %ecx 0/imm32
23070       0f 84/jump-if-= break/disp32
23071       # if (expected == 0) error
23072       81 7/subop/compare %edx 0/imm32
23073       0f 84/jump-if-= break/disp32
23074 $check-mu-call:check-output-type:
23075       # var v/eax: (addr v) = lookup(outputs->value)
23076       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23077       # var t/ebx: (addr type-tree) = lookup(v->type)
23078       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23079       89/<- %ebx 0/r32/eax
23080       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
23081       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23082       {
23083         74/jump-if-= break/disp8
23084         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23085         89/<- %ebx 0/r32/eax
23086       }
23087       # var v2/eax: (addr v) = lookup(expected->value)
23088       (lookup *edx *(edx+4))  # List-value List-value => eax
23089       # var t2/eax: (addr type-tree) = lookup(v2->type)
23090       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23091       # if (t != t2) error
23092       (type-match? %eax %ebx *(ebp-4))  # => eax
23093       3d/compare-eax-and 0/imm32/false
23094       {
23095         0f 85/jump-if-!= break/disp32
23096         (write-buffered *(ebp+0x14) "fn ")
23097         8b/-> *(ebp+0x10) 0/r32/eax
23098         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23099         (write-buffered *(ebp+0x14) %eax)
23100         (write-buffered *(ebp+0x14) ": call ")
23101         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23102         (write-buffered *(ebp+0x14) %eax)
23103         (write-buffered *(ebp+0x14) ": type for output '")
23104         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23105         (lookup *eax *(eax+4))  # Var-name Var-name => eax
23106         (write-buffered *(ebp+0x14) %eax)
23107         (write-buffered *(ebp+0x14) "' is not right\n")
23108         (flush *(ebp+0x14))
23109         (stop *(ebp+0x18) 1)
23110       }
23111 $check-mu-call:check-output-register:
23112       # var v/eax: (addr v) = lookup(outputs->value)
23113       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23114       # var r/ebx: (addr array byte) = lookup(v->register)
23115       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
23116       89/<- %ebx 0/r32/eax
23117       # if (r == 0) error
23118       3d/compare-eax-and 0/imm32
23119       {
23120         0f 85/jump-if-!= break/disp32
23121         (write-buffered *(ebp+0x14) "fn ")
23122         8b/-> *(ebp+0x10) 0/r32/eax
23123         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23124         (write-buffered *(ebp+0x14) %eax)
23125         (write-buffered *(ebp+0x14) ": call ")
23126         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23127         (write-buffered *(ebp+0x14) %eax)
23128         (write-buffered *(ebp+0x14) ": output '")
23129         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23130         (lookup *eax *(eax+4))  # Var-name Var-name => eax
23131         (write-buffered *(ebp+0x14) %eax)
23132         (write-buffered *(ebp+0x14) "' is not in a register\n")
23133         (flush *(ebp+0x14))
23134         (stop *(ebp+0x18) 1)
23135       }
23136       # var v2/eax: (addr v) = lookup(expected->value)
23137       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
23138       # var r2/eax: (addr array byte) = lookup(v2->register)
23139       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
23140       # if (r != r2) error
23141       (string-equal? %eax %ebx)  # => eax
23142       3d/compare-eax-and 0/imm32/false
23143       {
23144         0f 85/jump-if-!= break/disp32
23145         (write-buffered *(ebp+0x14) "fn ")
23146         8b/-> *(ebp+0x10) 0/r32/eax
23147         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23148         (write-buffered *(ebp+0x14) %eax)
23149         (write-buffered *(ebp+0x14) ": call ")
23150         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23151         (write-buffered *(ebp+0x14) %eax)
23152         (write-buffered *(ebp+0x14) ": register for output '")
23153         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23154         (lookup *eax *(eax+4))  # Var-name Var-name => eax
23155         (write-buffered *(ebp+0x14) %eax)
23156         (write-buffered *(ebp+0x14) "' is not right\n")
23157         (flush *(ebp+0x14))
23158         (stop *(ebp+0x18) 1)
23159       }
23160 $check-mu-call:continue-to-next-output:
23161       # outputs = lookup(outputs->next)
23162       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
23163       89/<- %ecx 0/r32/eax
23164       # expected = lookup(expected->next)
23165       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
23166       89/<- %edx 0/r32/eax
23167       #
23168       e9/jump loop/disp32
23169     }
23170 $check-mu-call:check-output-count:
23171     # if (outputs == expected) proceed
23172     39/compare %ecx 2/r32/edx
23173     {
23174       0f 84/jump-if-= break/disp32
23175       # exactly one of the two is null
23176       # if (outputs == 0) error("too many outputs")
23177       {
23178         81 7/subop/compare %ecx 0/imm32
23179         0f 84/jump-if-= break/disp32
23180         (write-buffered *(ebp+0x14) "fn ")
23181         8b/-> *(ebp+0x10) 0/r32/eax
23182         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23183         (write-buffered *(ebp+0x14) %eax)
23184         (write-buffered *(ebp+0x14) ": call ")
23185         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23186         (write-buffered *(ebp+0x14) %eax)
23187         (write-buffered *(ebp+0x14) ": too many outputs\n")
23188         (flush *(ebp+0x14))
23189         (stop *(ebp+0x18) 1)
23190       }
23191       # if (expected == 0) error("too few outputs")
23192       {
23193         81 7/subop/compare %edx 0/imm32
23194         0f 84/jump-if-= break/disp32
23195         (write-buffered *(ebp+0x14) "fn ")
23196         8b/-> *(ebp+0x10) 0/r32/eax
23197         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23198         (write-buffered *(ebp+0x14) %eax)
23199         (write-buffered *(ebp+0x14) ": call ")
23200         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23201         (write-buffered *(ebp+0x14) %eax)
23202         (write-buffered *(ebp+0x14) ": too few outputs\n")
23203         (flush *(ebp+0x14))
23204         (stop *(ebp+0x18) 1)
23205       }
23206     }
23207 $check-mu-call:end:
23208     # . restore registers
23209     5f/pop-to-edi
23210     5e/pop-to-esi
23211     5b/pop-to-ebx
23212     5a/pop-to-edx
23213     59/pop-to-ecx
23214     58/pop-to-eax
23215     # . reclaim locals exclusively on the stack
23216     81 0/subop/add %esp 0x70/imm32
23217     # . epilogue
23218     89/<- %esp 5/r32/ebp
23219     5d/pop-to-ebp
23220     c3/return
23221 
23222 # like type-equal? but takes literals type parameters into account
23223 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
23224     # . prologue
23225     55/push-ebp
23226     89/<- %ebp 4/r32/esp
23227     # if (call is literal and def is numberlike) return true
23228     {
23229 $type-match?:check-literal-int:
23230       (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
23231       3d/compare-eax-and 0/imm32/false
23232       74/jump-if-= break/disp8
23233       (is-mu-numberlike-output? *(ebp+8))  # => eax
23234       3d/compare-eax-and 0/imm32/false
23235       74/jump-if-= break/disp8
23236       b8/copy-to-eax 1/imm32/true
23237       e9/jump $type-match?:end/disp32
23238     }
23239     # if (call is literal-string and def is string) return true
23240     {
23241 $type-match?:check-literal-string:
23242       (is-simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
23243       3d/compare-eax-and 0/imm32/false
23244       74/jump-if-= break/disp8
23245       (is-mu-string-type? *(ebp+8))  # => eax
23246       3d/compare-eax-and 0/imm32/false
23247       74/jump-if-= break/disp8
23248       b8/copy-to-eax 1/imm32/true
23249       e9/jump $type-match?:end/disp32
23250     }
23251 $type-match?:baseline:
23252     # otherwise fall back
23253     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
23254 $type-match?:end:
23255     # . epilogue
23256     89/<- %esp 5/r32/ebp
23257     5d/pop-to-ebp
23258     c3/return
23259 
23260 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
23261     # . prologue
23262     55/push-ebp
23263     89/<- %ebp 4/r32/esp
23264     # . save registers
23265     51/push-ecx
23266     52/push-edx
23267     53/push-ebx
23268     # ecx = def
23269     8b/-> *(ebp+8) 1/r32/ecx
23270     # edx = call
23271     8b/-> *(ebp+0xc) 2/r32/edx
23272 $type-component-match?:compare-addr:
23273     # if (def == call) return true
23274     8b/-> %ecx 0/r32/eax  # Var-type
23275     39/compare %edx 0/r32/eax  # Var-type
23276     b8/copy-to-eax 1/imm32/true
23277     0f 84/jump-if-= $type-component-match?:end/disp32
23278     # if (def == 0) return false
23279     b8/copy-to-eax 0/imm32/false
23280     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
23281     0f 84/jump-if-= $type-component-match?:end/disp32
23282     # if (call == 0) return false
23283     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
23284     0f 84/jump-if-= $type-component-match?:end/disp32
23285     # if def is a type parameter, just check in type-parameters
23286     {
23287 $type-component-match?:check-type-parameter:
23288       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23289       74/jump-if-= break/disp8
23290       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
23291       75/jump-if-!= break/disp8
23292 $type-component-match?:type-parameter:
23293       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
23294       e9/jump $type-component-match?:end/disp32
23295     }
23296     # if def is a list containing just a type parameter, just check in type-parameters
23297     {
23298 $type-component-match?:check-list-type-parameter:
23299       # if def is a list..
23300       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23301       75/jump-if-!= break/disp8
23302       #   ..that's a singleton
23303       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
23304       75/jump-if-!= break/disp8
23305       #   ..and whose head is a type parameter
23306       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23307       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23308       74/jump-if-= break/disp8
23309       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
23310       75/jump-if-!= break/disp8
23311 $type-component-match?:list-type-parameter:
23312       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
23313       e9/jump $type-component-match?:end/disp32
23314     }
23315 $type-component-match?:compare-atom-state:
23316     # if (def->is-atom? != call->is-atom?) return false
23317     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
23318     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
23319     b8/copy-to-eax 0/imm32/false
23320     0f 85/jump-if-!= $type-component-match?:end/disp32
23321     # if def->is-atom? return (def->value == call->value)
23322     {
23323 $type-component-match?:check-atom:
23324       81 7/subop/compare %ebx 0/imm32/false
23325       74/jump-if-= break/disp8
23326 $type-component-match?:is-atom:
23327       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
23328       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
23329       0f 94/set-if-= %al
23330       81 4/subop/and %eax 0xff/imm32
23331       e9/jump $type-component-match?:end/disp32
23332     }
23333 $type-component-match?:check-left:
23334     # if (!type-component-match?(def->left, call->left)) return false
23335     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23336     89/<- %ebx 0/r32/eax
23337     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23338     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
23339     3d/compare-eax-and 0/imm32/false
23340     74/jump-if-= $type-component-match?:end/disp8
23341 $type-component-match?:check-right:
23342     # return type-component-match?(def->right, call->right)
23343     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23344     89/<- %ebx 0/r32/eax
23345     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
23346     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
23347 $type-component-match?:end:
23348     # . restore registers
23349     5b/pop-to-ebx
23350     5a/pop-to-edx
23351     59/pop-to-ecx
23352     # . epilogue
23353     89/<- %esp 5/r32/ebp
23354     5d/pop-to-ebp
23355     c3/return
23356 
23357 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
23358     # . prologue
23359     55/push-ebp
23360     89/<- %ebp 4/r32/esp
23361     # . save registers
23362     51/push-ecx
23363     #
23364     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
23365     # if parameter wasn't saved, save it
23366     {
23367       81 7/subop/compare *eax 0/imm32
23368       75/jump-if-!= break/disp8
23369       8b/-> *(ebp+0x10) 1/r32/ecx
23370       89/<- *eax 1/r32/ecx
23371     }
23372     #
23373     (type-equal? *(ebp+0x10) *eax)  # => eax
23374 $type-parameter-match?:end:
23375     # . restore registers
23376     59/pop-to-ecx
23377     # . epilogue
23378     89/<- %esp 5/r32/ebp
23379     5d/pop-to-ebp
23380     c3/return
23381 
23382 size-of:  # v: (addr var) -> result/eax: int
23383     # . prologue
23384     55/push-ebp
23385     89/<- %ebp 4/r32/esp
23386     # . save registers
23387     51/push-ecx
23388     # var t/ecx: (addr type-tree) = lookup(v->type)
23389     8b/-> *(ebp+8) 1/r32/ecx
23390 #?     (write-buffered Stderr "size-of ")
23391 #?     (write-int32-hex-buffered Stderr %ecx)
23392 #?     (write-buffered Stderr Newline)
23393 #?     (write-buffered Stderr "type allocid: ")
23394 #?     (write-int32-hex-buffered Stderr *(ecx+8))
23395 #?     (write-buffered Stderr Newline)
23396 #?     (flush Stderr)
23397     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23398     89/<- %ecx 0/r32/eax
23399     # if is-mu-array?(t) return size-of-array(t)
23400     {
23401       (is-mu-array? %ecx)  # => eax
23402       3d/compare-eax-and 0/imm32/false
23403       74/jump-if-= break/disp8
23404       (size-of-array %ecx)  # => eax
23405       eb/jump $size-of:end/disp8
23406     }
23407     # if is-mu-stream?(t) return size-of-stream(t)
23408     {
23409       (is-mu-stream? %ecx)  # => eax
23410       3d/compare-eax-and 0/imm32/false
23411       74/jump-if-= break/disp8
23412       (size-of-stream %ecx)  # => eax
23413       eb/jump $size-of:end/disp8
23414     }
23415     # if (!t->is-atom?) t = lookup(t->left)
23416     {
23417       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23418       75/jump-if-!= break/disp8
23419       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23420       89/<- %ecx 0/r32/eax
23421     }
23422     # TODO: assert t->is-atom?
23423     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
23424 $size-of:end:
23425     # . restore registers
23426     59/pop-to-ecx
23427     # . epilogue
23428     89/<- %esp 5/r32/ebp
23429     5d/pop-to-ebp
23430     c3/return
23431 
23432 size-of-deref:  # v: (addr var) -> result/eax: int
23433     # . prologue
23434     55/push-ebp
23435     89/<- %ebp 4/r32/esp
23436     # . save registers
23437     51/push-ecx
23438     # var t/ecx: (addr type-tree) = lookup(v->type)
23439     8b/-> *(ebp+8) 1/r32/ecx
23440     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23441     89/<- %ecx 0/r32/eax
23442     # TODO: assert(t is an addr)
23443     # t = lookup(t->right)
23444     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23445     89/<- %ecx 0/r32/eax
23446     # if is-mu-array?(t) return size-of-array(t)
23447     {
23448       (is-mu-array? %ecx)  # => eax
23449       3d/compare-eax-and 0/imm32/false
23450       74/jump-if-= break/disp8
23451       (size-of-array %ecx)  # => eax
23452       eb/jump $size-of-deref:end/disp8
23453     }
23454     # if is-mu-stream?(t) return size-of-stream(t)
23455     {
23456       (is-mu-stream? %ecx)  # => eax
23457       3d/compare-eax-and 0/imm32/false
23458       74/jump-if-= break/disp8
23459       (size-of-stream %ecx)  # => eax
23460       eb/jump $size-of-deref:end/disp8
23461     }
23462     # if (!t->is-atom?) t = lookup(t->left)
23463     {
23464       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23465       75/jump-if-!= break/disp8
23466       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23467       89/<- %ecx 0/r32/eax
23468     }
23469     # TODO: assert t->is-atom?
23470     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
23471 $size-of-deref:end:
23472     # . restore registers
23473     59/pop-to-ecx
23474     # . epilogue
23475     89/<- %esp 5/r32/ebp
23476     5d/pop-to-ebp
23477     c3/return
23478 
23479 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
23480     # . prologue
23481     55/push-ebp
23482     89/<- %ebp 4/r32/esp
23483     # . save registers
23484     51/push-ecx
23485     # ecx = t
23486     8b/-> *(ebp+8) 1/r32/ecx
23487     # if t->is-atom?, return false
23488     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23489     75/jump-if-!= $is-mu-array?:return-false/disp8
23490     # if !t->left->is-atom?, return false
23491     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23492     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23493     74/jump-if-= $is-mu-array?:return-false/disp8
23494     # return t->left->value == array
23495     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
23496     0f 94/set-if-= %al
23497     81 4/subop/and %eax 0xff/imm32
23498     eb/jump $is-mu-array?:end/disp8
23499 $is-mu-array?:return-false:
23500     b8/copy-to-eax 0/imm32/false
23501 $is-mu-array?:end:
23502     # . restore registers
23503     59/pop-to-ecx
23504     # . epilogue
23505     89/<- %esp 5/r32/ebp
23506     5d/pop-to-ebp
23507     c3/return
23508 
23509 # size of a statically allocated array where the size is part of the type expression
23510 size-of-array:  # a: (addr type-tree) -> result/eax: int
23511     # . prologue
23512     55/push-ebp
23513     89/<- %ebp 4/r32/esp
23514     # . save registers
23515     51/push-ecx
23516     52/push-edx
23517     #
23518     8b/-> *(ebp+8) 1/r32/ecx
23519     # TODO: assert that a->left is 'array'
23520     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23521     89/<- %ecx 0/r32/eax
23522     # var elem-type/edx: type-id = a->right->left->value
23523     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23524     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
23525     # TODO: assert that a->right->right->left->value == size
23526     # var array-size/ecx: int = a->right->right->left->value-size
23527     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23528     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23529     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
23530     # return 4 + array-size * size-of(elem-type)
23531     (size-of-type-id-as-array-element %edx)  # => eax
23532     f7 4/subop/multiply-into-edx-eax %ecx
23533     05/add-to-eax 4/imm32  # for array size
23534     # TODO: check edx for overflow
23535 $size-of-array:end:
23536     # . restore registers
23537     5a/pop-to-edx
23538     59/pop-to-ecx
23539     # . epilogue
23540     89/<- %esp 5/r32/ebp
23541     5d/pop-to-ebp
23542     c3/return
23543 
23544 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
23545     # . prologue
23546     55/push-ebp
23547     89/<- %ebp 4/r32/esp
23548     # . save registers
23549     51/push-ecx
23550     # ecx = t
23551     8b/-> *(ebp+8) 1/r32/ecx
23552     # if t->is-atom?, return false
23553     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23554     75/jump-if-!= $is-mu-stream?:return-false/disp8
23555     # if !t->left->is-atom?, return false
23556     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23557     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23558     74/jump-if-= $is-mu-stream?:return-false/disp8
23559     # return t->left->value == stream
23560     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
23561     0f 94/set-if-= %al
23562     81 4/subop/and %eax 0xff/imm32
23563     eb/jump $is-mu-stream?:end/disp8
23564 $is-mu-stream?:return-false:
23565     b8/copy-to-eax 0/imm32/false
23566 $is-mu-stream?:end:
23567     # . restore registers
23568     59/pop-to-ecx
23569     # . epilogue
23570     89/<- %esp 5/r32/ebp
23571     5d/pop-to-ebp
23572     c3/return
23573 
23574 # size of a statically allocated stream where the size is part of the type expression
23575 size-of-stream:  # a: (addr type-tree) -> result/eax: int
23576     # . prologue
23577     55/push-ebp
23578     89/<- %ebp 4/r32/esp
23579     #
23580     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
23581     05/add-to-eax 8/imm32  # for read/write pointers
23582 $size-of-stream:end:
23583     # . epilogue
23584     89/<- %esp 5/r32/ebp
23585     5d/pop-to-ebp
23586     c3/return
23587 
23588 size-of-type-id:  # t: type-id -> result/eax: int
23589     # . prologue
23590     55/push-ebp
23591     89/<- %ebp 4/r32/esp
23592     # . save registers
23593     51/push-ecx
23594     # var out/ecx: (handle typeinfo)
23595     68/push 0/imm32
23596     68/push 0/imm32
23597     89/<- %ecx 4/r32/esp
23598     # eax = t
23599     8b/-> *(ebp+8) 0/r32/eax
23600     # if t is a literal, return 0
23601     3d/compare-eax-and 0/imm32
23602     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
23603     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
23604     3d/compare-eax-and 8/imm32/byte
23605     {
23606       75/jump-if-!= break/disp8
23607       b8/copy-to-eax 4/imm32
23608       eb/jump $size-of-type-id:end/disp8
23609     }
23610     # if t is a handle, return 8
23611     3d/compare-eax-and 4/imm32/handle
23612     {
23613       75/jump-if-!= break/disp8
23614       b8/copy-to-eax 8/imm32
23615       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
23616     }
23617     # if t is a slice, return 8
23618     3d/compare-eax-and 0xc/imm32/slice
23619     {
23620       75/jump-if-!= break/disp8
23621       b8/copy-to-eax 8/imm32
23622       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
23623     }
23624     # if t is a user-defined type, return its size
23625     # TODO: support non-atom type
23626     (find-typeinfo %eax %ecx)
23627     {
23628       81 7/subop/compare *ecx 0/imm32
23629       74/jump-if-= break/disp8
23630 $size-of-type-id:user-defined:
23631       (lookup *ecx *(ecx+4))  # => eax
23632       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
23633       eb/jump $size-of-type-id:end/disp8
23634     }
23635     # otherwise return the word size
23636     b8/copy-to-eax 4/imm32
23637 $size-of-type-id:end:
23638     # . reclaim locals
23639     81 0/subop/add %esp 8/imm32
23640     # . restore registers
23641     59/pop-to-ecx
23642     # . epilogue
23643     89/<- %esp 5/r32/ebp
23644     5d/pop-to-ebp
23645     c3/return
23646 
23647 # Minor violation of our type system since it returns an addr. But we could
23648 # replace it with a handle some time.
23649 # Returns null if t is an atom.
23650 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
23651     # . prologue
23652     55/push-ebp
23653     89/<- %ebp 4/r32/esp
23654     # . save registers
23655     51/push-ecx
23656     # eax = 0
23657     b8/copy-to-eax 0/imm32
23658     # ecx = t
23659     8b/-> *(ebp+8) 1/r32/ecx
23660 $type-tail:check-atom:
23661     # if t->is-atom? return 0
23662     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23663     0f 85/jump-if-!= $type-tail:end/disp32
23664     # var tail = t->right
23665     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23666     89/<- %ecx 0/r32/eax
23667 $type-tail:check-singleton:
23668     # if (tail->right == 0) return tail->left
23669     {
23670       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
23671       75/jump-if-!= break/disp8
23672       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23673       e9/jump $type-tail:end/disp32
23674     }
23675     # if tail->right->left is an array-capacity, return tail->left
23676     {
23677 $type-tail:check-array-capacity:
23678       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23679       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23680       75/jump-if-!= break/disp8
23681 $type-tail:check-array-capacity-1:
23682       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23683       3d/compare-eax-and 0/imm32
23684       74/jump-if-= break/disp8
23685 $type-tail:check-array-capacity-2:
23686       (is-simple-mu-type? %eax 9)  # array-capacity => eax
23687       3d/compare-eax-and 0/imm32/false
23688       74/jump-if-= break/disp8
23689 $type-tail:array-capacity:
23690       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23691       eb/jump $type-tail:end/disp8
23692     }
23693 $type-tail:check-compound-left:
23694     # if !tail->left->is-atom? return tail->left
23695     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23696     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23697     74/jump-if-= $type-tail:end/disp8
23698 $type-tail:return-tail:
23699     # return tail
23700     89/<- %eax 1/r32/ecx
23701 $type-tail:end:
23702     # . restore registers
23703     59/pop-to-ecx
23704     # . epilogue
23705     89/<- %esp 5/r32/ebp
23706     5d/pop-to-ebp
23707     c3/return
23708 
23709 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23710     # . prologue
23711     55/push-ebp
23712     89/<- %ebp 4/r32/esp
23713     # . save registers
23714     51/push-ecx
23715     52/push-edx
23716     53/push-ebx
23717     # ecx = a
23718     8b/-> *(ebp+8) 1/r32/ecx
23719     # edx = b
23720     8b/-> *(ebp+0xc) 2/r32/edx
23721 $type-equal?:compare-addr:
23722     # if (a == b) return true
23723     8b/-> %ecx 0/r32/eax  # Var-type
23724     39/compare %edx 0/r32/eax  # Var-type
23725     b8/copy-to-eax 1/imm32/true
23726     0f 84/jump-if-= $type-equal?:end/disp32
23727 $type-equal?:compare-null-a:
23728     # if (a == 0) return false
23729     b8/copy-to-eax 0/imm32/false
23730     81 7/subop/compare %ecx 0/imm32
23731     0f 84/jump-if-= $type-equal?:end/disp32
23732 $type-equal?:compare-null-b:
23733     # if (b == 0) return false
23734     81 7/subop/compare %edx 0/imm32
23735     0f 84/jump-if-= $type-equal?:end/disp32
23736 $type-equal?:compare-atom-state:
23737     # if (a->is-atom? != b->is-atom?) return false
23738     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
23739     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
23740     b8/copy-to-eax 0/imm32/false
23741     0f 85/jump-if-!= $type-equal?:end/disp32
23742     # if a->is-atom? return (a->value == b->value)
23743     {
23744 $type-equal?:check-atom:
23745       81 7/subop/compare %ebx 0/imm32/false
23746       74/jump-if-= break/disp8
23747 $type-equal?:is-atom:
23748       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
23749       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
23750       0f 94/set-if-= %al
23751       81 4/subop/and %eax 0xff/imm32
23752       e9/jump $type-equal?:end/disp32
23753     }
23754 $type-equal?:check-left:
23755     # if (!type-equal?(a->left, b->left)) return false
23756     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23757     89/<- %ebx 0/r32/eax
23758     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23759     (type-equal? %eax %ebx)  # => eax
23760     3d/compare-eax-and 0/imm32/false
23761     74/jump-if-= $type-equal?:end/disp8
23762 $type-equal?:check-right:
23763     # return type-equal?(a->right, b->right)
23764     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23765     89/<- %ebx 0/r32/eax
23766     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
23767     (type-equal? %eax %ebx)  # => eax
23768 $type-equal?:end:
23769     # . restore registers
23770     5b/pop-to-ebx
23771     5a/pop-to-edx
23772     59/pop-to-ecx
23773     # . epilogue
23774     89/<- %esp 5/r32/ebp
23775     5d/pop-to-ebp
23776     c3/return
23777 
23778 #######################################################
23779 # Code-generation
23780 #######################################################
23781 
23782 == data
23783 
23784 # Global state added to each var record when performing code-generation.
23785 Curr-local-stack-offset:  # (addr int)
23786     0/imm32
23787 
23788 == code
23789 
23790 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
23791     # . prologue
23792     55/push-ebp
23793     89/<- %ebp 4/r32/esp
23794     # . save registers
23795     50/push-eax
23796     # var curr/eax: (addr function) = *Program->functions
23797     (lookup *_Program-functions *_Program-functions->payload)  # => eax
23798     {
23799       # if (curr == null) break
23800       3d/compare-eax-and 0/imm32
23801       0f 84/jump-if-= break/disp32
23802       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
23803       # curr = lookup(curr->next)
23804       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
23805       e9/jump loop/disp32
23806     }
23807 $emit-subx:end:
23808     # . restore registers
23809     58/pop-to-eax
23810     # . epilogue
23811     89/<- %esp 5/r32/ebp
23812     5d/pop-to-ebp
23813     c3/return
23814 
23815 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23816     # . prologue
23817     55/push-ebp
23818     89/<- %ebp 4/r32/esp
23819     # some preprocessing
23820     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
23821     # . save registers
23822     50/push-eax
23823     51/push-ecx
23824     52/push-edx
23825     # initialize some global state
23826     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
23827     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
23828     # ecx = f
23829     8b/-> *(ebp+0xc) 1/r32/ecx
23830     # var vars/edx: (stack (addr var) 256)
23831     81 5/subop/subtract %esp 0xc00/imm32
23832     68/push 0xc00/imm32/size
23833     68/push 0/imm32/top
23834     89/<- %edx 4/r32/esp
23835     # var name/eax: (addr array byte) = lookup(f->name)
23836     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
23837     #
23838     (write-buffered *(ebp+8) %eax)
23839     (write-buffered *(ebp+8) ":\n")
23840     (emit-subx-prologue *(ebp+8))
23841     # var body/eax: (addr block) = lookup(f->body)
23842     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
23843     #
23844     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
23845     (emit-subx-epilogue *(ebp+8))
23846     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
23847     # been cleaned up
23848 $emit-subx-function:end:
23849     # . reclaim locals
23850     81 0/subop/add %esp 0xc08/imm32
23851     # . restore registers
23852     5a/pop-to-edx
23853     59/pop-to-ecx
23854     58/pop-to-eax
23855     # . epilogue
23856     89/<- %esp 5/r32/ebp
23857     5d/pop-to-ebp
23858     c3/return
23859 
23860 populate-mu-type-offsets-in-inouts:  # f: (addr function)
23861     # . prologue
23862     55/push-ebp
23863     89/<- %ebp 4/r32/esp
23864     # . save registers
23865     50/push-eax
23866     51/push-ecx
23867     52/push-edx
23868     53/push-ebx
23869     57/push-edi
23870     # var next-offset/edx: int = 8
23871     ba/copy-to-edx 8/imm32
23872     # var curr/ecx: (addr list var) = lookup(f->inouts)
23873     8b/-> *(ebp+8) 1/r32/ecx
23874     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
23875     89/<- %ecx 0/r32/eax
23876     {
23877 $populate-mu-type-offsets-in-inouts:loop:
23878       81 7/subop/compare %ecx 0/imm32
23879       74/jump-if-= break/disp8
23880       # var v/ebx: (addr var) = lookup(curr->value)
23881       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23882       89/<- %ebx 0/r32/eax
23883 #?       (lookup *ebx *(ebx+4))
23884 #?       (write-buffered Stderr "setting offset of fn inout ")
23885 #?       (write-buffered Stderr %eax)
23886 #?       (write-buffered Stderr "@")
23887 #?       (write-int32-hex-buffered Stderr %ebx)
23888 #?       (write-buffered Stderr " to ")
23889 #?       (write-int32-hex-buffered Stderr %edx)
23890 #?       (write-buffered Stderr Newline)
23891 #?       (flush Stderr)
23892       # v->offset = next-offset
23893       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
23894       # next-offset += size-of(v)
23895       (size-of %ebx)  # => eax
23896       01/add-to %edx 0/r32/eax
23897       # curr = lookup(curr->next)
23898       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23899       89/<- %ecx 0/r32/eax
23900       #
23901       eb/jump loop/disp8
23902     }
23903 $populate-mu-type-offsets-in-inouts:end:
23904     # . restore registers
23905     5f/pop-to-edi
23906     5b/pop-to-ebx
23907     5a/pop-to-edx
23908     59/pop-to-ecx
23909     58/pop-to-eax
23910     # . epilogue
23911     89/<- %esp 5/r32/ebp
23912     5d/pop-to-ebp
23913     c3/return
23914 
23915 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)
23916     # . prologue
23917     55/push-ebp
23918     89/<- %ebp 4/r32/esp
23919     # . save registers
23920     50/push-eax
23921     51/push-ecx
23922     53/push-ebx
23923     56/push-esi
23924     # esi = stmts
23925     8b/-> *(ebp+0xc) 6/r32/esi
23926     #
23927     {
23928 $emit-subx-stmt-list:loop:
23929       81 7/subop/compare %esi 0/imm32
23930       0f 84/jump-if-= break/disp32
23931       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
23932       (lookup *esi *(esi+4))  # List-value List-value => eax
23933       89/<- %ecx 0/r32/eax
23934       {
23935 $emit-subx-stmt-list:check-for-block:
23936         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
23937         75/jump-if-!= break/disp8
23938 $emit-subx-stmt-list:block:
23939         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
23940       }
23941       {
23942 $emit-subx-stmt-list:check-for-stmt:
23943         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
23944         0f 85/jump-if-!= break/disp32
23945 $emit-subx-stmt-list:stmt1:
23946         {
23947           (is-mu-branch? %ecx)  # => eax
23948           3d/compare-eax-and 0/imm32/false
23949           0f 84/jump-if-= break/disp32
23950 $emit-subx-stmt-list:branch-stmt:
23951 +-- 25 lines: # unconditional return -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
23976 +-- 27 lines: # unconditional loops --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
24003 +-- 16 lines: # unconditional breaks -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
24019 +-- 38 lines: # simple conditional branches without a target -------------------------------------------------------------------------------------------------------------------------------------------------------
24057 +-- 19 lines: # conditional branches with an explicit target -------------------------------------------------------------------------------------------------------------------------------------------------------
24076         }
24077 $emit-subx-stmt-list:1-to-1:
24078         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
24079         e9/jump $emit-subx-stmt-list:continue/disp32
24080       }
24081       {
24082 $emit-subx-stmt-list:check-for-var-def:
24083         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
24084         75/jump-if-!= break/disp8
24085 $emit-subx-stmt-list:var-def:
24086         (emit-subx-var-def *(ebp+8) %ecx)
24087         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
24088         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
24089         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
24090         #
24091         eb/jump $emit-subx-stmt-list:continue/disp8
24092       }
24093       {
24094 $emit-subx-stmt-list:check-for-reg-var-def:
24095         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
24096         0f 85/jump-if-!= break/disp32
24097 $emit-subx-stmt-list:reg-var-def:
24098         # TODO: ensure that there's exactly one output
24099         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
24100         # emit the instruction as usual
24101         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
24102         #
24103         eb/jump $emit-subx-stmt-list:continue/disp8
24104       }
24105 $emit-subx-stmt-list:continue:
24106       # TODO: raise an error on unrecognized Stmt-tag
24107       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
24108       89/<- %esi 0/r32/eax
24109       e9/jump loop/disp32
24110     }
24111 $emit-subx-stmt-list:emit-cleanup:
24112     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
24113 $emit-subx-stmt-list:clean-up:
24114     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
24115     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
24116 $emit-subx-stmt-list:end:
24117     # . restore registers
24118     5e/pop-to-esi
24119     5b/pop-to-ebx
24120     59/pop-to-ecx
24121     58/pop-to-eax
24122     # . epilogue
24123     89/<- %esp 5/r32/ebp
24124     5d/pop-to-ebp
24125     c3/return
24126 
24127 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
24128 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)
24129     # . prologue
24130     55/push-ebp
24131     89/<- %ebp 4/r32/esp
24132     # . save registers
24133     50/push-eax
24134     51/push-ecx
24135     52/push-edx
24136     # ecx = stmt
24137     8b/-> *(ebp+0xc) 1/r32/ecx
24138     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
24139     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
24140     # TODO: assert !sv->is-deref?
24141     # var v/ecx: (addr var) = lookup(sv->value)
24142     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24143     89/<- %ecx 0/r32/eax
24144     # v->block-depth = *Curr-block-depth
24145     8b/-> *Curr-block-depth 0/r32/eax
24146     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
24147 #?     (write-buffered Stderr "var ")
24148 #?     (lookup *ecx *(ecx+4))
24149 #?     (write-buffered Stderr %eax)
24150 #?     (write-buffered Stderr " at depth ")
24151 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
24152 #?     (write-buffered Stderr Newline)
24153 #?     (flush Stderr)
24154     # ensure that v is in a register
24155     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24156     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
24157     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
24158     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
24159     89/<- %edx 0/r32/eax
24160     3d/compare-eax-and 0/imm32/false
24161     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
24162     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
24163     89/<- %edx 0/r32/eax
24164     # check emit-spill?
24165     3d/compare-eax-and 0/imm32/false
24166     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
24167     # TODO: assert(size-of(output) == 4)
24168     # *Curr-local-stack-offset -= 4
24169     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
24170     # emit spill
24171     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
24172     (emit-push-register *(ebp+8) %eax)
24173 $push-output-and-maybe-emit-spill:push:
24174     8b/-> *(ebp+0xc) 1/r32/ecx
24175     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
24176     # push(vars, {sv->value, emit-spill?})
24177     (push *(ebp+0x10) *eax)  # Stmt-var-value
24178     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
24179     (push *(ebp+0x10) %edx)
24180 $push-output-and-maybe-emit-spill:end:
24181     # . restore registers
24182     5a/pop-to-edx
24183     59/pop-to-ecx
24184     58/pop-to-eax
24185     # . epilogue
24186     89/<- %esp 5/r32/ebp
24187     5d/pop-to-ebp
24188     c3/return
24189 
24190 $push-output-and-maybe-emit-spill:abort:
24191     # error("var '" var->name "' initialized from an instruction must live in a register\n")
24192     (write-buffered *(ebp+0x1c) "var '")
24193     (write-buffered *(ebp+0x1c) *eax)  # Var-name
24194     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
24195     (flush *(ebp+0x1c))
24196     (stop *(ebp+0x20) 1)
24197     # never gets here
24198 
24199 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
24200     # . prologue
24201     55/push-ebp
24202     89/<- %ebp 4/r32/esp
24203     # . save registers
24204     50/push-eax
24205     51/push-ecx
24206     # ecx = stmt
24207     8b/-> *(ebp+0xc) 1/r32/ecx
24208     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
24209     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24210     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24211     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24212     # clean up until target block
24213     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
24214     # emit jump to target block
24215     (emit-indent *(ebp+8) *Curr-block-depth)
24216     (write-buffered *(ebp+8) "e9/jump ")
24217     (write-buffered *(ebp+8) %eax)
24218     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
24219     (string-starts-with? %eax "break")
24220     3d/compare-eax-and 0/imm32/false
24221     {
24222       74/jump-if-= break/disp8
24223       (write-buffered *(ebp+8) ":break/disp32\n")
24224       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
24225     }
24226     (write-buffered *(ebp+8) ":loop/disp32\n")
24227 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
24228     # . restore registers
24229     59/pop-to-ecx
24230     58/pop-to-eax
24231     # . epilogue
24232     89/<- %esp 5/r32/ebp
24233     5d/pop-to-ebp
24234     c3/return
24235 
24236 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
24237     # pseudocode:
24238     #   for every inout, output in return-stmt, fn->outputs
24239     #     if inout is a literal
24240     #       c7 0/subop/copy %output inout/imm32
24241     #     otherwise
24242     #       8b/-> inout %output
24243     #
24244     # . prologue
24245     55/push-ebp
24246     89/<- %ebp 4/r32/esp
24247     # . save registers
24248     50/push-eax
24249     51/push-ecx
24250     56/push-esi
24251     57/push-edi
24252     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
24253     8b/-> *(ebp+0xc) 0/r32/eax
24254     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24255     89/<- %esi 0/r32/eax
24256     # var curr-output/edi: (addr list var) = fn->outputs
24257     8b/-> *(ebp+0x10) 0/r32/eax
24258     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
24259     89/<- %edi 0/r32/eax
24260     {
24261 $emit-outputs:loop:
24262       81 7/subop/compare %esi 0/imm32
24263       0f 84/jump-if-= break/disp32
24264       # emit copy to output register
24265       # var curr-var/ecx = lookup(curr-inout->value)
24266       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24267       89/<- %ecx 0/r32/eax
24268       # if curr-var is a literal, emit copy of a literal to the output
24269       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24270       (is-simple-mu-type? %eax 0)  # literal => eax
24271       {
24272         3d/compare-eax-and 0/imm32/false
24273         0f 84/jump-if-= break/disp32
24274         (emit-indent *(ebp+8) *Curr-block-depth)
24275         (write-buffered *(ebp+8) "c7 0/subop/copy %")
24276         (lookup *edi *(edi+4))  # List-value List-value => eax
24277         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24278         (write-buffered *(ebp+8) %eax)
24279         (write-buffered *(ebp+8) " ")
24280         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24281         (write-buffered *(ebp+8) %eax)
24282         (write-buffered *(ebp+8) "/imm32\n")
24283         e9/jump $emit-outputs:continue/disp32
24284       }
24285       # if the non-literal is a register starting with "x", emit a floating-point copy
24286       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
24287       {
24288         3d/compare-eax-and 0/imm32
24289         0f 84/jump-if-= break/disp32
24290         8a/copy-byte *(eax+4) 0/r32/AL
24291         81 4/subop/and %eax 0xff/imm32
24292         3d/compare-eax-and 0x78/imm32/x
24293         0f 85/jump-if-!= break/disp32
24294         (emit-indent *(ebp+8) *Curr-block-depth)
24295         (write-buffered *(ebp+8) "f3 0f 10/->")
24296         (emit-subx-var-as-rm32 *(ebp+8) %esi)
24297         (write-buffered *(ebp+8) " ")
24298         (lookup *edi *(edi+4))  # List-value List-value => eax
24299         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24300         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
24301         (write-int32-hex-buffered *(ebp+8) *eax)
24302         (write-buffered *(ebp+8) "/x32\n")
24303         e9/jump $emit-outputs:continue/disp32
24304       }
24305       # otherwise emit an integer copy
24306       (emit-indent *(ebp+8) *Curr-block-depth)
24307       (write-buffered *(ebp+8) "8b/->")
24308       (emit-subx-var-as-rm32 *(ebp+8) %esi)
24309       (write-buffered *(ebp+8) " ")
24310       (lookup *edi *(edi+4))  # List-value List-value => eax
24311       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24312       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
24313       (write-int32-hex-buffered *(ebp+8) *eax)
24314       (write-buffered *(ebp+8) "/r32\n")
24315 $emit-outputs:continue:
24316       # curr-inout = curr-inout->next
24317       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
24318       89/<- %esi 0/r32/eax
24319       # curr-output = curr-output->next
24320       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
24321       89/<- %edi 0/r32/eax
24322       #
24323       e9/jump loop/disp32
24324     }
24325 $emit-outputs:end:
24326     # . restore registers
24327     5f/pop-to-edi
24328     5e/pop-to-esi
24329     59/pop-to-ecx
24330     58/pop-to-eax
24331     # . epilogue
24332     89/<- %esp 5/r32/ebp
24333     5d/pop-to-ebp
24334     c3/return
24335 
24336 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
24337     # . prologue
24338     55/push-ebp
24339     89/<- %ebp 4/r32/esp
24340     # . save registers
24341     51/push-ecx
24342     # ecx = lookup(stmt->operation)
24343     8b/-> *(ebp+8) 1/r32/ecx
24344     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
24345     89/<- %ecx 0/r32/eax
24346     # if (stmt->operation starts with "loop") return true
24347     (string-starts-with? %ecx "loop")  # => eax
24348     3d/compare-eax-and 0/imm32/false
24349     75/jump-if-not-equal $is-mu-branch?:end/disp8
24350     # if (stmt->operation starts with "break") return true
24351     (string-starts-with? %ecx "break")  # => eax
24352     3d/compare-eax-and 0/imm32/false
24353     75/jump-if-not-equal $is-mu-branch?:end/disp8
24354     # otherwise return (stmt->operation starts with "return")
24355     (string-starts-with? %ecx "return")  # => eax
24356 $is-mu-branch?:end:
24357     # . restore registers
24358     59/pop-to-ecx
24359     # . epilogue
24360     89/<- %esp 5/r32/ebp
24361     5d/pop-to-ebp
24362     c3/return
24363 
24364 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
24365     # . prologue
24366     55/push-ebp
24367     89/<- %ebp 4/r32/esp
24368     # . save registers
24369     50/push-eax
24370     # eax = stmt
24371     8b/-> *(ebp+0xc) 0/r32/eax
24372     #
24373     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
24374     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
24375     (emit-indent *(ebp+8) *Curr-block-depth)
24376     (lookup *eax *(eax+4))  # => eax
24377     (write-buffered *(ebp+8) %eax)
24378     (write-buffered *(ebp+8) " break/disp32\n")
24379 $emit-reverse-break:end:
24380     # . restore registers
24381     58/pop-to-eax
24382     # . epilogue
24383     89/<- %esp 5/r32/ebp
24384     5d/pop-to-ebp
24385     c3/return
24386 
24387 == data
24388 
24389 # Table from Mu branch instructions to the reverse SubX opcodes for them.
24390 Reverse-branch:  # (table (handle array byte) (handle array byte))
24391   # a table is a stream
24392   0x1c0/imm32/write
24393   0/imm32/read
24394   0x1c0/imm32/size
24395   # data
24396   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
24397   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
24398   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
24399   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
24400   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
24401   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
24402   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
24403   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
24404   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
24405   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
24406   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
24407   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
24408   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
24409   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
24410   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
24411   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
24412   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
24413   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
24414   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
24415   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
24416   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
24417   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
24418   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
24419   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
24420   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
24421   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
24422   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
24423   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
24424 
24425 == code
24426 
24427 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
24428     # . prologue
24429     55/push-ebp
24430     89/<- %ebp 4/r32/esp
24431     # . save registers
24432     50/push-eax
24433     51/push-ecx
24434     52/push-edx
24435     53/push-ebx
24436     56/push-esi
24437     # ecx = vars
24438     8b/-> *(ebp+0xc) 1/r32/ecx
24439     # var eax: int = vars->top
24440     8b/-> *ecx 0/r32/eax
24441     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
24442     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
24443     # var min/ecx: (addr handle var) = vars->data
24444     8d/copy-address *(ecx+8) 1/r32/ecx
24445     # edx = depth
24446     8b/-> *(ebp+0x10) 2/r32/edx
24447     {
24448 $emit-unconditional-jump-to-depth:loop:
24449       # if (curr < min) break
24450       39/compare %esi 1/r32/ecx
24451       0f 82/jump-if-addr< break/disp32
24452       # var v/ebx: (addr var) = lookup(*curr)
24453       (lookup *esi *(esi+4))  # => eax
24454       89/<- %ebx 0/r32/eax
24455       # if (v->block-depth < until-block-depth) break
24456       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
24457       0f 8c/jump-if-< break/disp32
24458       {
24459 $emit-unconditional-jump-to-depth:check:
24460         # if v->block-depth != until-block-depth, continue
24461         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
24462         0f 85/jump-if-!= break/disp32
24463 $emit-unconditional-jump-to-depth:depth-found:
24464         # if v is not a literal, continue
24465         (size-of %ebx)  # => eax
24466         3d/compare-eax-and 0/imm32
24467         0f 85/jump-if-!= break/disp32
24468 $emit-unconditional-jump-to-depth:label-found:
24469         # emit unconditional jump, then return
24470         (emit-indent *(ebp+8) *Curr-block-depth)
24471         (write-buffered *(ebp+8) "e9/jump ")
24472         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
24473         (write-buffered *(ebp+8) %eax)
24474         (write-buffered *(ebp+8) ":")
24475         (write-buffered *(ebp+8) *(ebp+0x14))
24476         (write-buffered *(ebp+8) "/disp32\n")
24477         eb/jump $emit-unconditional-jump-to-depth:end/disp8
24478       }
24479       # curr -= 12
24480       81 5/subop/subtract %esi 0xc/imm32
24481       e9/jump loop/disp32
24482     }
24483     # TODO: error if no label at 'depth' was found
24484 $emit-unconditional-jump-to-depth:end:
24485     # . restore registers
24486     5e/pop-to-esi
24487     5b/pop-to-ebx
24488     5a/pop-to-edx
24489     59/pop-to-ecx
24490     58/pop-to-eax
24491     # . epilogue
24492     89/<- %esp 5/r32/ebp
24493     5d/pop-to-ebp
24494     c3/return
24495 
24496 # emit clean-up code for 'vars' until some block depth
24497 # doesn't actually modify 'vars' so we need traverse manually inside the stack
24498 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
24499     # . prologue
24500     55/push-ebp
24501     89/<- %ebp 4/r32/esp
24502     # . save registers
24503     50/push-eax
24504     51/push-ecx
24505     52/push-edx
24506     53/push-ebx
24507     56/push-esi
24508 #?     (write-buffered Stderr "--- cleanup\n")
24509 #?     (flush Stderr)
24510     # ecx = vars
24511     8b/-> *(ebp+0xc) 1/r32/ecx
24512     # var esi: int = vars->top
24513     8b/-> *ecx 6/r32/esi
24514     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
24515     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
24516     # var min/ecx: (addr handle var) = vars->data
24517     81 0/subop/add %ecx 8/imm32
24518     # edx = until-block-depth
24519     8b/-> *(ebp+0x10) 2/r32/edx
24520     {
24521 $emit-cleanup-code-until-depth:loop:
24522       # if (curr < min) break
24523       39/compare %esi 1/r32/ecx
24524       0f 82/jump-if-addr< break/disp32
24525       # var v/ebx: (addr var) = lookup(*curr)
24526       (lookup *esi *(esi+4))  # => eax
24527       89/<- %ebx 0/r32/eax
24528 #?       (lookup *ebx *(ebx+4))  # Var-name
24529 #?       (write-buffered Stderr "var ")
24530 #?       (write-buffered Stderr %eax)
24531 #?       (write-buffered Stderr Newline)
24532 #?       (flush Stderr)
24533       # if (v->block-depth < until-block-depth) break
24534       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
24535       0f 8c/jump-if-< break/disp32
24536       # if v is in a register
24537       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
24538       {
24539         0f 84/jump-if-= break/disp32
24540         {
24541 $emit-cleanup-code-until-depth:check-for-previous-spill:
24542           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
24543           3d/compare-eax-and 0/imm32/false
24544           74/jump-if-= break/disp8
24545 $emit-cleanup-code-until-depth:reclaim-var-in-register:
24546           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
24547           (emit-pop-register *(ebp+8) %eax)
24548         }
24549         eb/jump $emit-cleanup-code-until-depth:continue/disp8
24550       }
24551       # otherwise v is on the stack
24552       {
24553         75/jump-if-!= break/disp8
24554 $emit-cleanup-code-until-depth:var-on-stack:
24555         (size-of %ebx)  # => eax
24556         # don't emit code for labels
24557         3d/compare-eax-and 0/imm32
24558         74/jump-if-= break/disp8
24559 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
24560         (emit-indent *(ebp+8) *Curr-block-depth)
24561         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
24562         (write-int32-hex-buffered *(ebp+8) %eax)
24563         (write-buffered *(ebp+8) "/imm32\n")
24564       }
24565 $emit-cleanup-code-until-depth:continue:
24566       # curr -= 12
24567       81 5/subop/subtract %esi 0xc/imm32
24568       e9/jump loop/disp32
24569     }
24570 $emit-cleanup-code-until-depth:end:
24571     # . restore registers
24572     5e/pop-to-esi
24573     5b/pop-to-ebx
24574     5a/pop-to-edx
24575     59/pop-to-ecx
24576     58/pop-to-eax
24577     # . epilogue
24578     89/<- %esp 5/r32/ebp
24579     5d/pop-to-ebp
24580     c3/return
24581 
24582 # emit clean-up code for 'vars' that don't conflict with output registers
24583 # doesn't actually modify 'vars' so we need traverse manually inside the stack
24584 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
24585     # . prologue
24586     55/push-ebp
24587     89/<- %ebp 4/r32/esp
24588     # . save registers
24589     50/push-eax
24590     51/push-ecx
24591     52/push-edx
24592     53/push-ebx
24593     56/push-esi
24594     57/push-edi
24595     # ecx = vars
24596     8b/-> *(ebp+0xc) 1/r32/ecx
24597     # var esi: int = vars->top
24598     8b/-> *ecx 6/r32/esi
24599     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
24600     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
24601     # var min/ecx: (addr handle var) = vars->data
24602     81 0/subop/add %ecx 8/imm32
24603     {
24604 $emit-cleanup-code-for-non-outputs:loop:
24605       # if (curr < min) break
24606       39/compare %esi 1/r32/ecx
24607       0f 82/jump-if-addr< break/disp32
24608       # var v/ebx: (addr var) = lookup(*curr)
24609       (lookup *esi *(esi+4))  # => eax
24610       89/<- %ebx 0/r32/eax
24611       # if v is in a register
24612       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
24613       {
24614         0f 84/jump-if-= break/disp32
24615         {
24616 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
24617           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
24618           3d/compare-eax-and 0/imm32/false
24619           0f 84/jump-if-= break/disp32
24620 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
24621           # var reg/edi: (addr array name) = v->register
24622           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
24623           89/<- %edi 0/r32/eax
24624           # if reg is not in function outputs, emit a pop
24625           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
24626           3d/compare-eax-and 0/imm32/false
24627           {
24628             75/jump-if-!= break/disp8
24629             (emit-pop-register *(ebp+8) %edi)
24630             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
24631           }
24632           # otherwise just drop it from the stack
24633           (emit-indent *(ebp+8) *Curr-block-depth)
24634           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
24635         }
24636 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
24637         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
24638       }
24639       # otherwise v is on the stack
24640       {
24641         75/jump-if-!= break/disp8
24642 $emit-cleanup-code-for-non-outputs:var-on-stack:
24643         (size-of %ebx)  # => eax
24644         # don't emit code for labels
24645         3d/compare-eax-and 0/imm32
24646         74/jump-if-= break/disp8
24647 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
24648         (emit-indent *(ebp+8) *Curr-block-depth)
24649         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
24650         (write-int32-hex-buffered *(ebp+8) %eax)
24651         (write-buffered *(ebp+8) "/imm32\n")
24652       }
24653 $emit-cleanup-code-for-non-outputs:continue:
24654       # curr -= 12
24655       81 5/subop/subtract %esi 0xc/imm32
24656       e9/jump loop/disp32
24657     }
24658 $emit-cleanup-code-for-non-outputs:end:
24659     # . restore registers
24660     5f/pop-to-edi
24661     5e/pop-to-esi
24662     5b/pop-to-ebx
24663     5a/pop-to-edx
24664     59/pop-to-ecx
24665     58/pop-to-eax
24666     # . epilogue
24667     89/<- %esp 5/r32/ebp
24668     5d/pop-to-ebp
24669     c3/return
24670 
24671 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
24672     # . prologue
24673     55/push-ebp
24674     89/<- %ebp 4/r32/esp
24675     # eax = reg
24676     8b/-> *(ebp+0xc) 0/r32/eax
24677     # var prefix/eax: byte = reg->data[0]
24678     8a/copy-byte *(eax+4) 0/r32/AL
24679     81 4/subop/and %eax 0xff/imm32
24680     # if (prefix == 'x') push xmm register
24681     {
24682       3d/compare-eax-and 0x78/imm32/x
24683       0f 85/jump-if-!= break/disp32
24684       # TODO validate register
24685       (emit-indent *(ebp+8) *Curr-block-depth)
24686       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
24687       (emit-indent *(ebp+8) *Curr-block-depth)
24688       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
24689       # var prefix/eax: byte = reg->data[3]
24690       8b/-> *(ebp+0xc) 0/r32/eax
24691       8a/copy-byte *(eax+7) 0/r32/AL
24692       81 4/subop/and %eax 0xff/imm32
24693       (write-byte-buffered *(ebp+8) %eax)
24694       (write-buffered *(ebp+8) "/x32\n")
24695       e9/jump $emit-push-register:end/disp32
24696     }
24697     # otherwise push gp register
24698     (emit-indent *(ebp+8) *Curr-block-depth)
24699     (write-buffered *(ebp+8) "ff 6/subop/push %")
24700     (write-buffered *(ebp+8) *(ebp+0xc))
24701     (write-buffered *(ebp+8) Newline)
24702 $emit-push-register:end:
24703     # . epilogue
24704     89/<- %esp 5/r32/ebp
24705     5d/pop-to-ebp
24706     c3/return
24707 
24708 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
24709     # . prologue
24710     55/push-ebp
24711     89/<- %ebp 4/r32/esp
24712     # . save registers
24713     50/push-eax
24714     # eax = reg
24715     8b/-> *(ebp+0xc) 0/r32/eax
24716     # var prefix/eax: byte = reg->data[0]
24717     8a/copy-byte *(eax+4) 0/r32/AL
24718     81 4/subop/and %eax 0xff/imm32
24719     # if (prefix == 'x') pop to xmm register
24720     {
24721       3d/compare-eax-and 0x78/imm32/x
24722       0f 85/jump-if-!= break/disp32
24723       # TODO validate register
24724       (emit-indent *(ebp+8) *Curr-block-depth)
24725       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
24726       # var prefix/eax: byte = reg->data[3]
24727       8b/-> *(ebp+0xc) 0/r32/eax
24728       8a/copy-byte *(eax+7) 0/r32/AL
24729       81 4/subop/and %eax 0xff/imm32
24730       (write-byte-buffered *(ebp+8) %eax)
24731       (write-buffered *(ebp+8) "/x32\n")
24732       (emit-indent *(ebp+8) *Curr-block-depth)
24733       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
24734       e9/jump $emit-pop-register:end/disp32
24735     }
24736     # otherwise pop to gp register
24737     (emit-indent *(ebp+8) *Curr-block-depth)
24738     (write-buffered *(ebp+8) "8f 0/subop/pop %")
24739     (write-buffered *(ebp+8) *(ebp+0xc))
24740     (write-buffered *(ebp+8) Newline)
24741 $emit-pop-register:end:
24742     # . restore registers
24743     58/pop-to-eax
24744     # . epilogue
24745     89/<- %esp 5/r32/ebp
24746     5d/pop-to-ebp
24747     c3/return
24748 
24749 # emit clean-up code for 'vars' until a given label is encountered
24750 # doesn't actually modify 'vars' so we need traverse manually inside the stack
24751 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
24752     # . prologue
24753     55/push-ebp
24754     89/<- %ebp 4/r32/esp
24755     # . save registers
24756     50/push-eax
24757     51/push-ecx
24758     52/push-edx
24759     53/push-ebx
24760     # ecx = vars
24761     8b/-> *(ebp+0xc) 1/r32/ecx
24762     # var eax: int = vars->top
24763     8b/-> *ecx 0/r32/eax
24764     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
24765     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
24766     # var min/ecx: (addr handle var) = vars->data
24767     81 0/subop/add %ecx 8/imm32
24768     {
24769 $emit-cleanup-code-until-target:loop:
24770       # if (curr < min) break
24771       39/compare %edx 1/r32/ecx
24772       0f 82/jump-if-addr< break/disp32
24773       # var v/ebx: (handle var) = lookup(*curr)
24774       (lookup *edx *(edx+4))  # => eax
24775       89/<- %ebx 0/r32/eax
24776       # if (v->name == until-block-label) break
24777       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
24778       (string-equal? %eax *(ebp+0x10))  # => eax
24779       3d/compare-eax-and 0/imm32/false
24780       0f 85/jump-if-!= break/disp32
24781       # if v is in a register
24782       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
24783       {
24784         0f 84/jump-if-= break/disp32
24785         {
24786 $emit-cleanup-code-until-target:check-for-previous-spill:
24787           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
24788           3d/compare-eax-and 0/imm32/false
24789           74/jump-if-= break/disp8
24790 $emit-cleanup-code-until-target:reclaim-var-in-register:
24791           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
24792           (emit-pop-register *(ebp+8) %eax)
24793         }
24794         eb/jump $emit-cleanup-code-until-target:continue/disp8
24795       }
24796       # otherwise v is on the stack
24797       {
24798         75/jump-if-!= break/disp8
24799 $emit-cleanup-code-until-target:reclaim-var-on-stack:
24800         (size-of %ebx)  # => eax
24801         # don't emit code for labels
24802         3d/compare-eax-and 0/imm32
24803         74/jump-if-= break/disp8
24804         #
24805         (emit-indent *(ebp+8) *Curr-block-depth)
24806         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
24807         (write-int32-hex-buffered *(ebp+8) %eax)
24808         (write-buffered *(ebp+8) "/imm32\n")
24809       }
24810 $emit-cleanup-code-until-target:continue:
24811       # curr -= 12
24812       81 5/subop/subtract %edx 0xc/imm32
24813       e9/jump loop/disp32
24814     }
24815 $emit-cleanup-code-until-target:end:
24816     # . restore registers
24817     5b/pop-to-ebx
24818     5a/pop-to-edx
24819     59/pop-to-ecx
24820     58/pop-to-eax
24821     # . epilogue
24822     89/<- %esp 5/r32/ebp
24823     5d/pop-to-ebp
24824     c3/return
24825 
24826 # update Curr-local-stack-offset assuming vars until some block depth are popped
24827 # doesn't actually modify 'vars', so we need traverse manually inside the stack
24828 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
24829     # . prologue
24830     55/push-ebp
24831     89/<- %ebp 4/r32/esp
24832     # . save registers
24833     50/push-eax
24834     51/push-ecx
24835     52/push-edx
24836     53/push-ebx
24837     56/push-esi
24838     # ecx = vars
24839     8b/-> *(ebp+8) 1/r32/ecx
24840     # var esi: int = vars->top
24841     8b/-> *ecx 6/r32/esi
24842     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
24843     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
24844     # var min/ecx: (addr handle var) = vars->data
24845     81 0/subop/add %ecx 8/imm32
24846     # edx = until-block-depth
24847     8b/-> *(ebp+0xc) 2/r32/edx
24848     {
24849 $clean-up-stack-offset-state:loop:
24850       # if (curr < min) break
24851       39/compare %esi 1/r32/ecx
24852       0f 82/jump-if-addr< break/disp32
24853       # var v/ebx: (addr var) = lookup(*curr)
24854       (lookup *esi *(esi+4))  # => eax
24855       89/<- %ebx 0/r32/eax
24856       # if (v->block-depth < until-block-depth) break
24857       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
24858       0f 8c/jump-if-< break/disp32
24859       # if v is in a register
24860       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
24861       {
24862         0f 84/jump-if-= break/disp32
24863         {
24864 $clean-up-stack-offset-state:check-for-previous-spill:
24865           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
24866           3d/compare-eax-and 0/imm32/false
24867           74/jump-if-= break/disp8
24868 $clean-up-stack-offset-state:reclaim-var-in-register:
24869           81 0/subop/add *Curr-local-stack-offset 4/imm32
24870         }
24871         eb/jump $clean-up-stack-offset-state:continue/disp8
24872       }
24873       # otherwise v is on the stack
24874       {
24875         75/jump-if-!= break/disp8
24876 $clean-up-stack-offset-state:var-on-stack:
24877         (size-of %ebx)  # => eax
24878         01/add-to *Curr-local-stack-offset 0/r32/eax
24879       }
24880 $clean-up-stack-offset-state:continue:
24881       # curr -= 12
24882       81 5/subop/subtract %esi 0xc/imm32
24883       e9/jump loop/disp32
24884     }
24885 $clean-up-stack-offset-state:end:
24886     # . restore registers
24887     5e/pop-to-esi
24888     5b/pop-to-ebx
24889     5a/pop-to-edx
24890     59/pop-to-ecx
24891     58/pop-to-eax
24892     # . epilogue
24893     89/<- %esp 5/r32/ebp
24894     5d/pop-to-ebp
24895     c3/return
24896 
24897 # Return true if there isn't a variable in 'vars' with the same block-depth
24898 # and register as 'v'.
24899 # 'v' is guaranteed not to be within 'vars'.
24900 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
24901     # . prologue
24902     55/push-ebp
24903     89/<- %ebp 4/r32/esp
24904     # . save registers
24905     51/push-ecx
24906     52/push-edx
24907     53/push-ebx
24908     56/push-esi
24909     57/push-edi
24910     # ecx = vars
24911     8b/-> *(ebp+0xc) 1/r32/ecx
24912     # var eax: int = vars->top
24913     8b/-> *ecx 0/r32/eax
24914     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
24915     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
24916     # var min/ecx: (addr handle var) = vars->data
24917     8d/copy-address *(ecx+8) 1/r32/ecx
24918     # var depth/ebx: int = v->block-depth
24919     8b/-> *(ebp+8) 3/r32/ebx
24920     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
24921     # var needle/esi: (addr array byte) = v->register
24922     8b/-> *(ebp+8) 6/r32/esi
24923     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
24924     89/<- %esi 0/r32/eax
24925     {
24926 $not-yet-spilled-this-block?:loop:
24927       # if (curr < min) break
24928       39/compare %edx 1/r32/ecx
24929       0f 82/jump-if-addr< break/disp32
24930       # var cand/edi: (addr var) = lookup(*curr)
24931       (lookup *edx *(edx+4))  # => eax
24932       89/<- %edi 0/r32/eax
24933       # if (cand->block-depth < depth) break
24934       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
24935       0f 8c/jump-if-< break/disp32
24936       # var cand-reg/edi: (array array byte) = cand->reg
24937       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
24938       89/<- %edi 0/r32/eax
24939       # if (cand-reg == null) continue
24940       {
24941 $not-yet-spilled-this-block?:check-reg:
24942         81 7/subop/compare %edi 0/imm32
24943         0f 84/jump-if-= break/disp32
24944         # if (cand-reg == needle) return true
24945         (string-equal? %esi %edi)  # => eax
24946         3d/compare-eax-and 0/imm32/false
24947         74/jump-if-= break/disp8
24948 $not-yet-spilled-this-block?:return-false:
24949         b8/copy-to-eax 0/imm32/false
24950         eb/jump $not-yet-spilled-this-block?:end/disp8
24951       }
24952 $not-yet-spilled-this-block?:continue:
24953       # curr -= 12
24954       81 5/subop/subtract %edx 0xc/imm32
24955       e9/jump loop/disp32
24956     }
24957 $not-yet-spilled-this-block?:return-true:
24958     # return true
24959     b8/copy-to-eax 1/imm32/true
24960 $not-yet-spilled-this-block?:end:
24961     # . restore registers
24962     5f/pop-to-edi
24963     5e/pop-to-esi
24964     5b/pop-to-ebx
24965     5a/pop-to-edx
24966     59/pop-to-ecx
24967     # . epilogue
24968     89/<- %esp 5/r32/ebp
24969     5d/pop-to-ebp
24970     c3/return
24971 
24972 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
24973 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
24974     # . prologue
24975     55/push-ebp
24976     89/<- %ebp 4/r32/esp
24977     # eax = v
24978     8b/-> *(ebp+8) 0/r32/eax
24979     # var reg/eax: (addr array byte) = lookup(v->register)
24980     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24981     # var target/eax: (addr var) = find-register(fn-outputs, reg)
24982     (find-register *(ebp+0x10) %eax)  # => eax
24983     # if (target == 0) return true
24984     {
24985       3d/compare-eax-and 0/imm32
24986       75/jump-if-!= break/disp8
24987       b8/copy-to-eax 1/imm32/true
24988       eb/jump $will-not-write-some-register?:end/disp8
24989     }
24990     # return !assigns-in-stmts?(stmts, target)
24991     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
24992     3d/compare-eax-and 0/imm32/false
24993     # assume: true = 1, so no need to mask with 0x000000ff
24994     0f 94/set-if-= %al
24995 $will-not-write-some-register?:end:
24996     # . epilogue
24997     89/<- %esp 5/r32/ebp
24998     5d/pop-to-ebp
24999     c3/return
25000 
25001 # return fn output with matching register
25002 # always returns false if 'reg' is null
25003 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
25004     # . prologue
25005     55/push-ebp
25006     89/<- %ebp 4/r32/esp
25007     # . save registers
25008     51/push-ecx
25009     # var curr/ecx: (addr list var) = lookup(fn->outputs)
25010     8b/-> *(ebp+8) 1/r32/ecx
25011     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
25012     89/<- %ecx 0/r32/eax
25013     {
25014 $find-register:loop:
25015       # if (curr == 0) break
25016       81 7/subop/compare %ecx 0/imm32
25017       74/jump-if-= break/disp8
25018       # eax = curr->value->register
25019       (lookup *ecx *(ecx+4))  # List-value List-value => eax
25020       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25021       # if (eax == reg) return curr->value
25022 $find-register:compare:
25023       (string-equal? *(ebp+0xc) %eax)  # => eax
25024       {
25025         3d/compare-eax-and 0/imm32/false
25026         74/jump-if-= break/disp8
25027 $find-register:found:
25028         (lookup *ecx *(ecx+4))  # List-value List-value => eax
25029         eb/jump $find-register:end/disp8
25030       }
25031       # curr = lookup(curr->next)
25032       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
25033       89/<- %ecx 0/r32/eax
25034       #
25035       eb/jump loop/disp8
25036     }
25037 $find-register:end:
25038     # . restore registers
25039     59/pop-to-ecx
25040     # . epilogue
25041     89/<- %esp 5/r32/ebp
25042     5d/pop-to-ebp
25043     c3/return
25044 
25045 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
25046     # . prologue
25047     55/push-ebp
25048     89/<- %ebp 4/r32/esp
25049     # . save registers
25050     51/push-ecx
25051     # var curr/ecx: (addr list stmt) = stmts
25052     8b/-> *(ebp+8) 1/r32/ecx
25053     {
25054       # if (curr == 0) break
25055       81 7/subop/compare %ecx 0/imm32
25056       74/jump-if-= break/disp8
25057       # if assigns-in-stmt?(curr->value, v) return true
25058       (lookup *ecx *(ecx+4))  # List-value List-value => eax
25059       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
25060       3d/compare-eax-and 0/imm32/false
25061       75/jump-if-!= break/disp8
25062       # curr = lookup(curr->next)
25063       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
25064       89/<- %ecx 0/r32/eax
25065       #
25066       eb/jump loop/disp8
25067     }
25068 $assigns-in-stmts?:end:
25069     # . restore registers
25070     59/pop-to-ecx
25071     # . epilogue
25072     89/<- %esp 5/r32/ebp
25073     5d/pop-to-ebp
25074     c3/return
25075 
25076 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
25077     # . prologue
25078     55/push-ebp
25079     89/<- %ebp 4/r32/esp
25080     # . save registers
25081     51/push-ecx
25082     # ecx = stmt
25083     8b/-> *(ebp+8) 1/r32/ecx
25084     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
25085     {
25086       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
25087       75/jump-if-!= break/disp8
25088       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25089       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
25090       eb/jump $assigns-in-stmt?:end/disp8
25091     }
25092     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
25093     {
25094       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
25095       75/jump-if-!= break/disp8
25096       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
25097       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
25098       eb/jump $assigns-in-stmt?:end/disp8
25099     }
25100     # otherwise return false
25101     b8/copy 0/imm32/false
25102 $assigns-in-stmt?:end:
25103     # . restore registers
25104     59/pop-to-ecx
25105     # . epilogue
25106     89/<- %esp 5/r32/ebp
25107     5d/pop-to-ebp
25108     c3/return
25109 
25110 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
25111     # . prologue
25112     55/push-ebp
25113     89/<- %ebp 4/r32/esp
25114     # . save registers
25115     51/push-ecx
25116     # var curr/ecx: (addr stmt-var) = stmt-var
25117     8b/-> *(ebp+8) 1/r32/ecx
25118     {
25119       # if (curr == 0) break
25120       81 7/subop/compare %ecx 0/imm32
25121       74/jump-if-= break/disp8
25122       # eax = lookup(curr->value)
25123       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
25124       # if (eax == v  &&  curr->is-deref? == false) return true
25125       {
25126         39/compare *(ebp+0xc) 0/r32/eax
25127         75/jump-if-!= break/disp8
25128         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
25129         75/jump-if-!= break/disp8
25130         b8/copy-to-eax 1/imm32/true
25131         eb/jump $assigns-in-stmt-vars?:end/disp8
25132       }
25133       # curr = lookup(curr->next)
25134       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
25135       89/<- %ecx 0/r32/eax
25136       #
25137       eb/jump loop/disp8
25138     }
25139 $assigns-in-stmt-vars?:end:
25140     # . restore registers
25141     59/pop-to-ecx
25142     # . epilogue
25143     89/<- %esp 5/r32/ebp
25144     5d/pop-to-ebp
25145     c3/return
25146 
25147 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
25148 # v is guaranteed to be within vars
25149 # 'start' is provided as an optimization, a pointer within vars
25150 # *start == v
25151 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
25152     # . prologue
25153     55/push-ebp
25154     89/<- %ebp 4/r32/esp
25155     # . save registers
25156     51/push-ecx
25157     52/push-edx
25158     53/push-ebx
25159     56/push-esi
25160     57/push-edi
25161     # ecx = v
25162     8b/-> *(ebp+8) 1/r32/ecx
25163     # var reg/edx: (addr array byte) = lookup(v->register)
25164     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25165     89/<- %edx 0/r32/eax
25166     # var depth/ebx: int = v->block-depth
25167     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
25168     # var min/ecx: (addr handle var) = vars->data
25169     8b/-> *(ebp+0xc) 1/r32/ecx
25170     81 0/subop/add %ecx 8/imm32
25171     # TODO: check that start >= min and start < &vars->data[top]
25172     # TODO: check that *start == v
25173     # var curr/esi: (addr handle var) = start
25174     8b/-> *(ebp+0x10) 6/r32/esi
25175     # curr -= 8
25176     81 5/subop/subtract %esi 8/imm32
25177     {
25178 $same-register-spilled-before?:loop:
25179       # if (curr < min) break
25180       39/compare %esi 1/r32/ecx
25181       0f 82/jump-if-addr< break/disp32
25182       # var x/eax: (addr var) = lookup(*curr)
25183       (lookup *esi *(esi+4))  # => eax
25184       # if (x->block-depth < depth) break
25185       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
25186       0f 8c/jump-if-< break/disp32
25187       # if (x->register == 0) continue
25188       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
25189       74/jump-if-= $same-register-spilled-before?:continue/disp8
25190       # if (x->register == reg) return true
25191       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25192       (string-equal? %eax %edx)  # => eax
25193       3d/compare-eax-and 0/imm32/false
25194       b8/copy-to-eax 1/imm32/true
25195       75/jump-if-!= $same-register-spilled-before?:end/disp8
25196 $same-register-spilled-before?:continue:
25197       # curr -= 8
25198       81 5/subop/subtract %esi 8/imm32
25199       e9/jump loop/disp32
25200     }
25201 $same-register-spilled-before?:false:
25202     b8/copy-to-eax 0/imm32/false
25203 $same-register-spilled-before?:end:
25204     # . restore registers
25205     5f/pop-to-edi
25206     5e/pop-to-esi
25207     5b/pop-to-ebx
25208     5a/pop-to-edx
25209     59/pop-to-ecx
25210     # . epilogue
25211     89/<- %esp 5/r32/ebp
25212     5d/pop-to-ebp
25213     c3/return
25214 
25215 # clean up global state for 'vars' until some block depth (inclusive)
25216 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
25217     # . prologue
25218     55/push-ebp
25219     89/<- %ebp 4/r32/esp
25220     # . save registers
25221     50/push-eax
25222     51/push-ecx
25223     56/push-esi
25224     # esi = vars
25225     8b/-> *(ebp+8) 6/r32/esi
25226     # ecx = until-block-depth
25227     8b/-> *(ebp+0xc) 1/r32/ecx
25228     {
25229 $clean-up-blocks:reclaim-loop:
25230       # if (vars->top <= 0) break
25231       8b/-> *esi 0/r32/eax  # Stack-top
25232       3d/compare-eax-and 0/imm32
25233       0f 8e/jump-if-<= break/disp32
25234       # var v/eax: (addr var) = lookup(vars[vars->top-12])
25235       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
25236       # if (v->block-depth < until-block-depth) break
25237       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
25238       0f 8c/jump-if-< break/disp32
25239       (pop %esi)  # => eax
25240       (pop %esi)  # => eax
25241       (pop %esi)  # => eax
25242       e9/jump loop/disp32
25243     }
25244 $clean-up-blocks:end:
25245     # . restore registers
25246     5e/pop-to-esi
25247     59/pop-to-ecx
25248     58/pop-to-eax
25249     # . epilogue
25250     89/<- %esp 5/r32/ebp
25251     5d/pop-to-ebp
25252     c3/return
25253 
25254 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
25255     # . prologue
25256     55/push-ebp
25257     89/<- %ebp 4/r32/esp
25258     # . save registers
25259     51/push-ecx
25260     # var curr/ecx: (addr list var) = lookup(fn->outputs)
25261     8b/-> *(ebp+8) 0/r32/eax
25262     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
25263     89/<- %ecx 0/r32/eax
25264     # while curr != null
25265     {
25266       81 7/subop/compare %ecx 0/imm32
25267       74/jump-if-= break/disp8
25268       # var v/eax: (addr var) = lookup(curr->value)
25269       (lookup *ecx *(ecx+4))  # List-value List-value => eax
25270       # var reg/eax: (addr array byte) = lookup(v->register)
25271       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25272       # if (reg == target) return true
25273       (string-equal? %eax *(ebp+0xc))  # => eax
25274       3d/compare-eax-and 0/imm32/false
25275       75/jump-if-!= $reg-in-function-outputs?:end/disp8
25276       # curr = curr->next
25277       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
25278       89/<- %ecx 0/r32/eax
25279       #
25280       eb/jump loop/disp8
25281     }
25282     # return false
25283     b8/copy-to-eax 0/imm32
25284 $reg-in-function-outputs?:end:
25285     # . restore registers
25286     59/pop-to-ecx
25287     # . epilogue
25288     89/<- %esp 5/r32/ebp
25289     5d/pop-to-ebp
25290     c3/return
25291 
25292 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
25293     # . prologue
25294     55/push-ebp
25295     89/<- %ebp 4/r32/esp
25296     # . save registers
25297     50/push-eax
25298     51/push-ecx
25299     52/push-edx
25300     # eax = stmt
25301     8b/-> *(ebp+0xc) 0/r32/eax
25302     # var v/ecx: (addr var)
25303     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
25304     89/<- %ecx 0/r32/eax
25305     # v->block-depth = *Curr-block-depth
25306     8b/-> *Curr-block-depth 0/r32/eax
25307     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
25308     # var n/edx: int = size-of(stmt->var)
25309     (size-of %ecx)  # => eax
25310     89/<- %edx 0/r32/eax
25311     # *Curr-local-stack-offset -= n
25312     29/subtract-from *Curr-local-stack-offset 2/r32/edx
25313     # v->offset = *Curr-local-stack-offset
25314     8b/-> *Curr-local-stack-offset 0/r32/eax
25315     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
25316     # if v is an array, do something special to initialize it
25317     {
25318       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25319       (is-mu-array? %eax)  # => eax
25320       3d/compare-eax-and 0/imm32/false
25321       0f 84/jump-if-= break/disp32
25322       # var array-size-without-size/edx: int = n-4
25323       81 5/subop/subtract %edx 4/imm32
25324       #
25325       (emit-array-data-initialization *(ebp+8) %edx)
25326       e9/jump $emit-subx-var-def:end/disp32
25327     }
25328     # another special-case for initializing streams
25329     # a stream is an array with 2 extra pointers
25330     {
25331       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25332       (is-mu-stream? %eax)  # => eax
25333       3d/compare-eax-and 0/imm32/false
25334       0f 84/jump-if-= break/disp32
25335       # var array-size-without-size/edx: int = n-12
25336       81 5/subop/subtract %edx 0xc/imm32
25337       (emit-array-data-initialization *(ebp+8) %edx)
25338       # emit read and write pointers
25339       (emit-indent *(ebp+8) *Curr-block-depth)
25340       (write-buffered *(ebp+8) "68/push 0/imm32\n")
25341       (emit-indent *(ebp+8) *Curr-block-depth)
25342       (write-buffered *(ebp+8) "68/push 0/imm32\n")
25343       #
25344       eb/jump $emit-subx-var-def:end/disp8
25345     }
25346     # while n > 0
25347     {
25348       81 7/subop/compare %edx 0/imm32
25349       7e/jump-if-<= break/disp8
25350       (emit-indent *(ebp+8) *Curr-block-depth)
25351       (write-buffered *(ebp+8) "68/push 0/imm32\n")
25352       # n -= 4
25353       81 5/subop/subtract %edx 4/imm32
25354       #
25355       eb/jump loop/disp8
25356     }
25357 $emit-subx-var-def:end:
25358     # . restore registers
25359     5a/pop-to-edx
25360     59/pop-to-ecx
25361     58/pop-to-eax
25362     # . epilogue
25363     89/<- %esp 5/r32/ebp
25364     5d/pop-to-ebp
25365     c3/return
25366 
25367 emit-array-data-initialization:  # out: (addr buffered-file), n: int
25368     # . prologue
25369     55/push-ebp
25370     89/<- %ebp 4/r32/esp
25371     #
25372     (emit-indent *(ebp+8) *Curr-block-depth)
25373     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
25374     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
25375     (write-buffered *(ebp+8) ")\n")
25376     (emit-indent *(ebp+8) *Curr-block-depth)
25377     (write-buffered *(ebp+8) "68/push ")
25378     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
25379     (write-buffered *(ebp+8) "/imm32\n")
25380 $emit-array-data-initialization:end:
25381     # . epilogue
25382     89/<- %esp 5/r32/ebp
25383     5d/pop-to-ebp
25384     c3/return
25385 
25386 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
25387     # . prologue
25388     55/push-ebp
25389     89/<- %ebp 4/r32/esp
25390     # . save registers
25391     50/push-eax
25392     51/push-ecx
25393     # - some special-case primitives that don't actually use the 'primitives' data structure
25394     # var op/ecx: (addr array byte) = lookup(stmt->operation)
25395     8b/-> *(ebp+0xc) 1/r32/ecx
25396     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25397     89/<- %ecx 0/r32/eax
25398     # array size
25399     {
25400       # if (!string-equal?(stmt->operation, "length")) break
25401       (string-equal? %ecx "length")  # => eax
25402       3d/compare-eax-and 0/imm32
25403       0f 84/jump-if-= break/disp32
25404       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25405       e9/jump $emit-subx-stmt:end/disp32
25406     }
25407     # index into array
25408     {
25409       # if (!string-equal?(stmt->operation, "index")) break
25410       (string-equal? %ecx "index")  # => eax
25411       3d/compare-eax-and 0/imm32
25412       0f 84/jump-if-= break/disp32
25413       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25414       e9/jump $emit-subx-stmt:end/disp32
25415     }
25416     # compute-offset for index into array
25417     {
25418       # if (!string-equal?(stmt->operation, "compute-offset")) break
25419       (string-equal? %ecx "compute-offset")  # => eax
25420       3d/compare-eax-and 0/imm32
25421       0f 84/jump-if-= break/disp32
25422       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25423       e9/jump $emit-subx-stmt:end/disp32
25424     }
25425     # get field from record
25426     {
25427       # if (!string-equal?(stmt->operation, "get")) break
25428       (string-equal? %ecx "get")  # => eax
25429       3d/compare-eax-and 0/imm32
25430       0f 84/jump-if-= break/disp32
25431       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
25432       e9/jump $emit-subx-stmt:end/disp32
25433     }
25434     # allocate scalar
25435     {
25436       # if (!string-equal?(stmt->operation, "allocate")) break
25437       (string-equal? %ecx "allocate")  # => eax
25438       3d/compare-eax-and 0/imm32
25439       0f 84/jump-if-= break/disp32
25440       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25441       e9/jump $emit-subx-stmt:end/disp32
25442     }
25443     # copy-object
25444     {
25445       # if (!string-equal?(stmt->operation, "copy-object")) break
25446       (string-equal? %ecx "copy-object")  # => eax
25447       3d/compare-eax-and 0/imm32
25448       0f 84/jump-if-= break/disp32
25449       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25450       e9/jump $emit-subx-stmt:end/disp32
25451     }
25452     # allocate array
25453     {
25454       # if (!string-equal?(stmt->operation, "populate")) break
25455       (string-equal? %ecx "populate")  # => eax
25456       3d/compare-eax-and 0/imm32
25457       0f 84/jump-if-= break/disp32
25458       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25459       e9/jump $emit-subx-stmt:end/disp32
25460     }
25461     # allocate stream
25462     {
25463       # if (!string-equal?(stmt->operation, "populate-stream")) break
25464       (string-equal? %ecx "populate-stream")  # => eax
25465       3d/compare-eax-and 0/imm32
25466       0f 84/jump-if-= break/disp32
25467       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25468       e9/jump $emit-subx-stmt:end/disp32
25469     }
25470     # read from stream
25471     {
25472       # if (!string-equal?(stmt->operation, "read-from-stream")) break
25473       (string-equal? %ecx "read-from-stream")  # => eax
25474       3d/compare-eax-and 0/imm32
25475       0f 84/jump-if-= break/disp32
25476       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25477       e9/jump $emit-subx-stmt:end/disp32
25478     }
25479     # write to stream
25480     {
25481       # if (!string-equal?(stmt->operation, "write-to-stream")) break
25482       (string-equal? %ecx "write-to-stream")  # => eax
25483       3d/compare-eax-and 0/imm32
25484       0f 84/jump-if-= break/disp32
25485       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
25486       e9/jump $emit-subx-stmt:end/disp32
25487     }
25488     # - if stmt matches a primitive, emit it
25489     {
25490 $emit-subx-stmt:check-for-primitive:
25491       # var curr/eax: (addr primitive)
25492       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
25493       3d/compare-eax-and 0/imm32
25494       74/jump-if-= break/disp8
25495 $emit-subx-stmt:primitive:
25496       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
25497       e9/jump $emit-subx-stmt:end/disp32
25498     }
25499     # - otherwise emit a call
25500     # TODO: type-checking
25501 $emit-subx-stmt:call:
25502     (emit-call *(ebp+8) *(ebp+0xc))
25503 $emit-subx-stmt:end:
25504     # . restore registers
25505     59/pop-to-ecx
25506     58/pop-to-eax
25507     # . epilogue
25508     89/<- %esp 5/r32/ebp
25509     5d/pop-to-ebp
25510     c3/return
25511 
25512 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25513     # . prologue
25514     55/push-ebp
25515     89/<- %ebp 4/r32/esp
25516     # . save registers
25517     50/push-eax
25518     51/push-ecx
25519     52/push-edx
25520     53/push-ebx
25521     56/push-esi
25522     # esi = stmt
25523     8b/-> *(ebp+0xc) 6/r32/esi
25524     # var base/ebx: (addr var) = stmt->inouts[0]->value
25525     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25526     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25527     89/<- %ebx 0/r32/eax
25528     # var elemsize/ecx: int = array-element-size(base)
25529     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
25530     89/<- %ecx 0/r32/eax
25531     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
25532     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25533     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25534     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25535     89/<- %edx 0/r32/eax
25536     # if elemsize == 1
25537     {
25538       81 7/subop/compare %ecx 1/imm32
25539       75/jump-if-!= break/disp8
25540 $translate-mu-length-stmt:size-1:
25541       (emit-save-size-to *(ebp+8) %ebx %edx)
25542       e9/jump $translate-mu-length-stmt:end/disp32
25543     }
25544     # if elemsize is a power of 2 less than 256
25545     {
25546       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
25547       3d/compare-eax-and 0/imm32/false
25548       74/jump-if-= break/disp8
25549       81 7/subop/compare %ecx 0xff/imm32
25550       7f/jump-if-> break/disp8
25551 $translate-mu-length-stmt:size-power-of-2:
25552       (emit-save-size-to *(ebp+8) %ebx %edx)
25553       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
25554       e9/jump $translate-mu-length-stmt:end/disp32
25555     }
25556     # otherwise, the complex case
25557     # . emit register spills
25558     {
25559 $translate-mu-length-stmt:complex:
25560       (string-equal? %edx "eax")  # => eax
25561       3d/compare-eax-and 0/imm32/false
25562       75/break-if-!= break/disp8
25563       (emit-indent *(ebp+8) *Curr-block-depth)
25564       (write-buffered *(ebp+8) "50/push-eax\n")
25565     }
25566     {
25567       (string-equal? %edx "ecx")  # => eax
25568       3d/compare-eax-and 0/imm32/false
25569       75/break-if-!= break/disp8
25570       (emit-indent *(ebp+8) *Curr-block-depth)
25571       (write-buffered *(ebp+8) "51/push-ecx\n")
25572     }
25573     {
25574       (string-equal? %edx "edx")  # => eax
25575       3d/compare-eax-and 0/imm32/false
25576       75/break-if-!= break/disp8
25577       (emit-indent *(ebp+8) *Curr-block-depth)
25578       (write-buffered *(ebp+8) "52/push-edx\n")
25579     }
25580     # .
25581     (emit-save-size-to *(ebp+8) %ebx "eax")
25582     (emit-indent *(ebp+8) *Curr-block-depth)
25583     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
25584     (emit-indent *(ebp+8) *Curr-block-depth)
25585     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
25586     (write-int32-hex-buffered *(ebp+8) %ecx)
25587     (write-buffered *(ebp+8) "/imm32\n")
25588     (emit-indent *(ebp+8) *Curr-block-depth)
25589     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
25590     {
25591       (string-equal? %edx "eax")  # => eax
25592       3d/compare-eax-and 0/imm32/false
25593       75/break-if-!= break/disp8
25594       (emit-indent *(ebp+8) *Curr-block-depth)
25595       (write-buffered *(ebp+8) "89/<- %")
25596       (write-buffered *(ebp+8) %edx)
25597       (write-buffered *(ebp+8) " 0/r32/eax\n")
25598     }
25599     # . emit register restores
25600     {
25601       (string-equal? %edx "edx")  # => eax
25602       3d/compare-eax-and 0/imm32/false
25603       75/break-if-!= break/disp8
25604       (emit-indent *(ebp+8) *Curr-block-depth)
25605       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
25606     }
25607     {
25608       (string-equal? %edx "ecx")  # => eax
25609       3d/compare-eax-and 0/imm32/false
25610       75/break-if-!= break/disp8
25611       (emit-indent *(ebp+8) *Curr-block-depth)
25612       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
25613     }
25614     {
25615       (string-equal? %edx "eax")  # => eax
25616       3d/compare-eax-and 0/imm32/false
25617       75/break-if-!= break/disp8
25618       (emit-indent *(ebp+8) *Curr-block-depth)
25619       (write-buffered *(ebp+8) "58/pop-to-eax\n")
25620     }
25621 $translate-mu-length-stmt:end:
25622     # . restore registers
25623     5e/pop-to-esi
25624     5b/pop-to-ebx
25625     5a/pop-to-edx
25626     59/pop-to-ecx
25627     58/pop-to-eax
25628     # . epilogue
25629     89/<- %esp 5/r32/ebp
25630     5d/pop-to-ebp
25631     c3/return
25632 
25633 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
25634     # . prologue
25635     55/push-ebp
25636     89/<- %ebp 4/r32/esp
25637     #
25638     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
25639     (size-of-type-id-as-array-element %eax)  # => eax
25640 $array-element-size:end:
25641     # . epilogue
25642     89/<- %esp 5/r32/ebp
25643     5d/pop-to-ebp
25644     c3/return
25645 
25646 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
25647     # precondition: n is positive
25648     # . prologue
25649     55/push-ebp
25650     89/<- %ebp 4/r32/esp
25651     #
25652     8b/-> *(ebp+8) 0/r32/eax
25653     # var t/eax: (addr type-tree)
25654     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25655     # if t == 0 abort
25656     3d/compare-eax-with 0/imm32
25657     0f 84/jump-if-== $array-element-type-id:error0/disp32
25658     # if t->is-atom? abort
25659     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25660     0f 85/jump-if-!= $array-element-type-id:error1/disp32
25661     # if (t->left == addr) t = t->right
25662     {
25663       50/push-eax
25664       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25665       (is-simple-mu-type? %eax 2)  # addr => eax
25666       3d/compare-eax-with 0/imm32/false
25667       58/pop-to-eax
25668       74/jump-if-= break/disp8
25669 $array-element-type-id:skip-addr:
25670       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25671     }
25672     # if t == 0 abort
25673     3d/compare-eax-with 0/imm32
25674     0f 84/jump-if-= $array-element-type-id:error2/disp32
25675     # if t->is-atom? abort
25676     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25677     0f 85/jump-if-!= $array-element-type-id:error2/disp32
25678     # if t->left != array abort
25679     {
25680       50/push-eax
25681       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25682       (is-simple-mu-type? %eax 3)  # array => eax
25683       3d/compare-eax-with 0/imm32/false
25684       58/pop-to-eax
25685 $array-element-type-id:no-array:
25686       0f 84/jump-if-= $array-element-type-id:error2/disp32
25687     }
25688 $array-element-type-id:skip-array:
25689     # t = t->right
25690     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
25691     # if t == 0 abort
25692     3d/compare-eax-with 0/imm32
25693     0f 84/jump-if-= $array-element-type-id:error2/disp32
25694     # if t->is-atom? abort
25695     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25696     0f 85/jump-if-!= $array-element-type-id:error2/disp32
25697     # t = t->left
25698     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25699     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
25700     # if (t->is-atom == false) t = lookup(t->left)
25701     {
25702       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25703       75/jump-if-!= break/disp8
25704       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25705     }
25706     # return t->value
25707     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
25708 $array-element-type-id:end:
25709     # . epilogue
25710     89/<- %esp 5/r32/ebp
25711     5d/pop-to-ebp
25712     c3/return
25713 
25714 $array-element-type-id:error0:
25715     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
25716     50/push-eax
25717     8b/-> *(ebp+8) 0/r32/eax
25718     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25719     (write-buffered *(ebp+0xc) %eax)
25720     58/pop-to-eax
25721     (write-buffered *(ebp+0xc) "' has no type\n")
25722     (flush *(ebp+0xc))
25723     (stop *(ebp+0x10) 1)
25724     # never gets here
25725 
25726 $array-element-type-id:error1:
25727     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
25728     50/push-eax
25729     8b/-> *(ebp+8) 0/r32/eax
25730     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25731     (write-buffered *(ebp+0xc) %eax)
25732     58/pop-to-eax
25733     (write-buffered *(ebp+0xc) "' has atomic type ")
25734     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
25735     (write-buffered *(ebp+0xc) Newline)
25736     (flush *(ebp+0xc))
25737     (stop *(ebp+0x10) 1)
25738     # never gets here
25739 
25740 $array-element-type-id:error2:
25741     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
25742     50/push-eax
25743     8b/-> *(ebp+8) 0/r32/eax
25744     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25745     (write-buffered *(ebp+0xc) %eax)
25746     58/pop-to-eax
25747     (write-buffered *(ebp+0xc) "' has non-array type\n")
25748     (flush *(ebp+0xc))
25749     (stop *(ebp+0x10) 1)
25750     # never gets here
25751 
25752 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
25753     # . prologue
25754     55/push-ebp
25755     89/<- %ebp 4/r32/esp
25756     # eax = t
25757     8b/-> *(ebp+8) 0/r32/eax
25758     # if t is 'byte', size is 1
25759     3d/compare-eax-and 8/imm32/byte
25760     {
25761       75/jump-if-!= break/disp8
25762       b8/copy-to-eax 1/imm32
25763       eb/jump $size-of-type-id-as-array-element:end/disp8
25764     }
25765     # otherwise proceed as usual
25766     (size-of-type-id %eax)  # => eax
25767 $size-of-type-id-as-array-element:end:
25768     # . epilogue
25769     89/<- %esp 5/r32/ebp
25770     5d/pop-to-ebp
25771     c3/return
25772 
25773 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
25774     # . prologue
25775     55/push-ebp
25776     89/<- %ebp 4/r32/esp
25777     # . save registers
25778     50/push-eax
25779     53/push-ebx
25780     # ebx = base
25781     8b/-> *(ebp+0xc) 3/r32/ebx
25782     (emit-indent *(ebp+8) *Curr-block-depth)
25783     (write-buffered *(ebp+8) "8b/-> *")
25784     # if base is an (addr array ...) in a register
25785     {
25786       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
25787       74/jump-if-= break/disp8
25788 $emit-save-size-to:emit-base-from-register:
25789       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25790       (write-buffered *(ebp+8) %eax)
25791       eb/jump $emit-save-size-to:emit-output/disp8
25792     }
25793     # otherwise if base is an (array ...) on the stack
25794     {
25795       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
25796       74/jump-if-= break/disp8
25797 $emit-save-size-to:emit-base-from-stack:
25798       (write-buffered *(ebp+8) "(ebp+")
25799       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
25800       (write-buffered *(ebp+8) ")")
25801     }
25802 $emit-save-size-to:emit-output:
25803     (write-buffered *(ebp+8) " ")
25804     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
25805     (write-int32-hex-buffered *(ebp+8) *eax)
25806     (write-buffered *(ebp+8) "/r32\n")
25807 $emit-save-size-to:end:
25808     # . restore registers
25809     5b/pop-to-ebx
25810     58/pop-to-eax
25811     # . epilogue
25812     89/<- %esp 5/r32/ebp
25813     5d/pop-to-ebp
25814     c3/return
25815 
25816 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
25817     # . prologue
25818     55/push-ebp
25819     89/<- %ebp 4/r32/esp
25820     # . save registers
25821     50/push-eax
25822     #
25823     (emit-indent *(ebp+8) *Curr-block-depth)
25824     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
25825     (write-buffered *(ebp+8) *(ebp+0xc))
25826     (write-buffered *(ebp+8) Space)
25827     (num-shift-rights *(ebp+0x10))  # => eax
25828     (write-int32-hex-buffered *(ebp+8) %eax)
25829     (write-buffered *(ebp+8) "/imm8\n")
25830 $emit-divide-by-shift-right:end:
25831     # . restore registers
25832     58/pop-to-eax
25833     # . epilogue
25834     89/<- %esp 5/r32/ebp
25835     5d/pop-to-ebp
25836     c3/return
25837 
25838 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25839     # . prologue
25840     55/push-ebp
25841     89/<- %ebp 4/r32/esp
25842     # . save registers
25843     51/push-ecx
25844     # ecx = stmt
25845     8b/-> *(ebp+0xc) 1/r32/ecx
25846     # var base/ecx: (addr var) = stmt->inouts[0]
25847     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25848     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25849     89/<- %ecx 0/r32/eax
25850     # if (var->register) do one thing
25851     {
25852       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
25853       74/jump-if-= break/disp8
25854       # TODO: ensure there's no dereference
25855       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
25856       eb/jump $translate-mu-index-stmt:end/disp8
25857     }
25858     # if (var->offset) do a different thing
25859     {
25860       81 7/subop/compare *(ecx+0x14) 0/imm32  # Var-offset
25861       74/jump-if-= break/disp8
25862       # TODO: ensure there's no dereference
25863       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
25864       eb/jump $translate-mu-index-stmt:end/disp8
25865     }
25866 $translate-mu-index-stmt:end:
25867     # . restore registers
25868     59/pop-to-ecx
25869     # . epilogue
25870     89/<- %esp 5/r32/ebp
25871     5d/pop-to-ebp
25872     c3/return
25873 
25874 $translate-mu-index-stmt-with-array:error1:
25875     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
25876     (flush *(ebp+0x10))
25877     (stop *(ebp+0x14) 1)
25878     # never gets here
25879 
25880 $translate-mu-index-stmt-with-array:error2:
25881     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
25882     (flush *(ebp+0x10))
25883     (stop *(ebp+0x14) 1)
25884     # never gets here
25885 
25886 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25887     # . prologue
25888     55/push-ebp
25889     89/<- %ebp 4/r32/esp
25890     # . save registers
25891     50/push-eax
25892     51/push-ecx
25893     52/push-edx
25894     53/push-ebx
25895     #
25896     (emit-indent *(ebp+8) *Curr-block-depth)
25897     (write-buffered *(ebp+8) "8d/copy-address *(")
25898     # TODO: ensure inouts[0] is in a register and not dereferenced
25899 $translate-mu-index-stmt-with-array-in-register:emit-base:
25900     # ecx = stmt
25901     8b/-> *(ebp+0xc) 1/r32/ecx
25902     # var base/ebx: (addr var) = inouts[0]
25903     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25904     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25905     89/<- %ebx 0/r32/eax
25906     # print base->register " + "
25907     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25908     (write-buffered *(ebp+8) %eax)
25909     (write-buffered *(ebp+8) " + ")
25910     # var index/edx: (addr var) = inouts[1]
25911     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25912     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25913     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25914     89/<- %edx 0/r32/eax
25915     # if index->register
25916     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
25917     {
25918       0f 84/jump-if-= break/disp32
25919 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
25920       # if index is an int
25921       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25922       (is-simple-mu-type? %eax 1)  # int => eax
25923       3d/compare-eax-and 0/imm32/false
25924       {
25925         0f 84/jump-if-= break/disp32
25926 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
25927         # print index->register "<<" log2(array-element-size(base)) " + 4) "
25928         # . index->register "<<"
25929         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
25930         (write-buffered *(ebp+8) %eax)
25931         (write-buffered *(ebp+8) "<<")
25932         # . log2(array-element-size(base->type))
25933         # TODO: ensure size is a power of 2
25934         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
25935         (num-shift-rights %eax)  # => eax
25936         (write-int32-hex-buffered *(ebp+8) %eax)
25937         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
25938       }
25939       # if index->type is any other atom, abort
25940       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25941       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25942       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
25943       # if index has type (offset ...)
25944       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25945       (is-simple-mu-type? %eax 7)  # => eax
25946       3d/compare-eax-and 0/imm32/false
25947       {
25948         0f 84/jump-if-= break/disp32
25949         # print index->register
25950 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
25951         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
25952         (write-buffered *(ebp+8) %eax)
25953       }
25954 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
25955       (write-buffered *(ebp+8) " + 4) ")
25956       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
25957     }
25958     # otherwise if index is a literal
25959     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
25960     (is-simple-mu-type? %eax 0)  # => eax
25961     3d/compare-eax-and 0/imm32/false
25962     {
25963       0f 84/jump-if-= break/disp32
25964 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
25965       # var index-value/edx: int = parse-hex-int(index->name)
25966       (lookup *edx *(edx+4))  # Var-name Var-name => eax
25967       (parse-hex-int %eax)  # => eax
25968       89/<- %edx 0/r32/eax
25969       # offset = idx-value * array-element-size(base->type)
25970       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
25971       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
25972       # offset += 4 for array size
25973       05/add-to-eax 4/imm32
25974       # TODO: check edx for overflow
25975       # print offset
25976       (write-int32-hex-buffered *(ebp+8) %eax)
25977       (write-buffered *(ebp+8) ") ")
25978       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
25979     }
25980     # otherwise abort
25981     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
25982 $translate-mu-index-stmt-with-array-in-register:emit-output:
25983     # outputs[0] "/r32"
25984     8b/-> *(ebp+0xc) 1/r32/ecx
25985     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25986     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25987     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25988     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
25989     (write-int32-hex-buffered *(ebp+8) *eax)
25990     (write-buffered *(ebp+8) "/r32\n")
25991 $translate-mu-index-stmt-with-array-in-register:end:
25992     # . restore registers
25993     5b/pop-to-ebx
25994     5a/pop-to-edx
25995     59/pop-to-ecx
25996     58/pop-to-eax
25997     # . epilogue
25998     89/<- %esp 5/r32/ebp
25999     5d/pop-to-ebp
26000     c3/return
26001 
26002 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26003     # . prologue
26004     55/push-ebp
26005     89/<- %ebp 4/r32/esp
26006     # . save registers
26007     50/push-eax
26008     51/push-ecx
26009     52/push-edx
26010     53/push-ebx
26011     #
26012     (emit-indent *(ebp+8) *Curr-block-depth)
26013     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
26014     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
26015     8b/-> *(ebp+0xc) 0/r32/eax
26016     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26017     89/<- %edx 0/r32/eax
26018     # var base/ecx: (addr var) = lookup(curr->value)
26019     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26020     89/<- %ecx 0/r32/eax
26021     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
26022     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
26023     # var index/edx: (handle var) = curr2->value
26024     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26025     89/<- %edx 0/r32/eax
26026     # if index->register
26027     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
26028     {
26029       0f 84/jump-if-= break/disp32
26030 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
26031       # if index is an int
26032       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26033       (is-simple-mu-type? %eax 1)  # int => eax
26034       3d/compare-eax-and 0/imm32/false
26035       {
26036         0f 84/jump-if-= break/disp32
26037 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
26038         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
26039         # . inouts[1]->register "<<"
26040         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
26041         (write-buffered *(ebp+8) %eax)
26042         (write-buffered *(ebp+8) "<<")
26043         # . log2(array-element-size(base))
26044         # TODO: ensure size is a power of 2
26045         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
26046         (num-shift-rights %eax)  # => eax
26047         (write-int32-hex-buffered *(ebp+8) %eax)
26048         #
26049         (write-buffered *(ebp+8) " + ")
26050         #
26051         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
26052         05/add-to-eax 4/imm32  # for array length
26053         (write-int32-hex-buffered *(ebp+8) %eax)
26054         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
26055       }
26056       # if index->type is any other atom, abort
26057       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26058       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26059       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
26060       # if index has type (offset ...)
26061       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26062       (is-simple-mu-type? %eax 7)  # => eax
26063       3d/compare-eax-and 0/imm32/false
26064       {
26065         0f 84/jump-if-= break/disp32
26066         # print index->register
26067 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
26068         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
26069         (write-buffered *(ebp+8) %eax)
26070       }
26071 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
26072       (write-buffered *(ebp+8) ") ")
26073       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
26074     }
26075     # otherwise if index is a literal
26076     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26077     (is-simple-mu-type? %eax 0)  # => eax
26078     3d/compare-eax-and 0/imm32/false
26079     {
26080       0f 84/jump-if-= break/disp32
26081 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
26082       # var idx-value/edx: int = parse-hex-int(index->name)
26083       (lookup *edx *(edx+4))  # Var-name Var-name => eax
26084       (parse-hex-int %eax)  # Var-name => eax
26085       89/<- %edx 0/r32/eax
26086       # offset = idx-value * array-element-size(base)
26087       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
26088       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
26089       # offset += base->offset
26090       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
26091       # offset += 4 for array size
26092       05/add-to-eax 4/imm32
26093       # TODO: check edx for overflow
26094       # print offset
26095       (write-int32-hex-buffered *(ebp+8) %eax)
26096       (write-buffered *(ebp+8) ") ")
26097       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
26098     }
26099     # otherwise abort
26100     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
26101 $translate-mu-index-stmt-with-array-on-stack:emit-output:
26102     # outputs[0] "/r32"
26103     8b/-> *(ebp+0xc) 0/r32/eax
26104     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26105     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26106     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26107     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
26108     (write-int32-hex-buffered *(ebp+8) *eax)
26109     (write-buffered *(ebp+8) "/r32\n")
26110 $translate-mu-index-stmt-with-array-on-stack:end:
26111     # . restore registers
26112     5b/pop-to-ebx
26113     5a/pop-to-edx
26114     59/pop-to-ecx
26115     58/pop-to-eax
26116     # . epilogue
26117     89/<- %esp 5/r32/ebp
26118     5d/pop-to-ebp
26119     c3/return
26120 
26121 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26122     # . prologue
26123     55/push-ebp
26124     89/<- %ebp 4/r32/esp
26125     # . save registers
26126     50/push-eax
26127     51/push-ecx
26128     52/push-edx
26129     53/push-ebx
26130     #
26131     (emit-indent *(ebp+8) *Curr-block-depth)
26132     (write-buffered *(ebp+8) "69/multiply")
26133     # ecx = stmt
26134     8b/-> *(ebp+0xc) 1/r32/ecx
26135     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
26136     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26137     89/<- %ebx 0/r32/eax
26138 $translate-mu-compute-index-stmt:emit-index:
26139     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
26140     (emit-subx-var-as-rm32 *(ebp+8) %eax)
26141     (write-buffered *(ebp+8) Space)
26142 $translate-mu-compute-index-stmt:emit-elem-size:
26143     # var base/ebx: (addr var)
26144     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
26145     89/<- %ebx 0/r32/eax
26146     # print array-element-size(base)
26147     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
26148     (write-int32-hex-buffered *(ebp+8) %eax)
26149     (write-buffered *(ebp+8) "/imm32 ")
26150 $translate-mu-compute-index-stmt:emit-output:
26151     # outputs[0] "/r32"
26152     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26153     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26154     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26155     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
26156     (write-int32-hex-buffered *(ebp+8) *eax)
26157     (write-buffered *(ebp+8) "/r32\n")
26158 $translate-mu-compute-index-stmt:end:
26159     # . restore registers
26160     5b/pop-to-ebx
26161     5a/pop-to-edx
26162     59/pop-to-ecx
26163     58/pop-to-eax
26164     # . epilogue
26165     89/<- %esp 5/r32/ebp
26166     5d/pop-to-ebp
26167     c3/return
26168 
26169 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
26170     # . prologue
26171     55/push-ebp
26172     89/<- %ebp 4/r32/esp
26173     # . save registers
26174     50/push-eax
26175     51/push-ecx
26176     52/push-edx
26177     #
26178     (emit-indent *(ebp+8) *Curr-block-depth)
26179     (write-buffered *(ebp+8) "8d/copy-address ")
26180     # ecx = stmt
26181     8b/-> *(ebp+0xc) 1/r32/ecx
26182     # var offset/edx: int = get offset of stmt
26183     (mu-get-offset %ecx)  # => eax
26184     89/<- %edx 0/r32/eax
26185     # var base/eax: (addr var) = stmt->inouts->value
26186     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26187     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26188     # if base is in a register
26189     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
26190     {
26191       0f 84/jump-if-= break/disp32
26192 $translate-mu-get-stmt:emit-register-input:
26193       # emit "*(" base->register " + " offset ") "
26194       (write-buffered *(ebp+8) "*(")
26195       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26196       (write-buffered *(ebp+8) %eax)
26197       (write-buffered *(ebp+8) " + ")
26198       (write-int32-hex-buffered *(ebp+8) %edx)
26199       (write-buffered *(ebp+8) ") ")
26200       e9/jump $translate-mu-get-stmt:emit-output/disp32
26201     }
26202     # otherwise base is on the stack
26203     {
26204 $translate-mu-get-stmt:emit-stack-input:
26205       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
26206       (write-buffered *(ebp+8) "*(ebp+")
26207       03/add *(eax+0x14) 2/r32/edx  # Var-offset
26208       (write-int32-hex-buffered *(ebp+8) %edx)
26209       (write-buffered *(ebp+8) ") ")
26210       eb/jump $translate-mu-get-stmt:emit-output/disp8
26211     }
26212 $translate-mu-get-stmt:emit-output:
26213     # var output/eax: (addr var) = stmt->outputs->value
26214     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26215     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26216     # emit offset->register "/r32"
26217     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26218     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
26219     (write-int32-hex-buffered *(ebp+8) *eax)
26220     (write-buffered *(ebp+8) "/r32\n")
26221 $translate-mu-get-stmt:end:
26222     # . restore registers
26223     5a/pop-to-edx
26224     59/pop-to-ecx
26225     58/pop-to-eax
26226     # . epilogue
26227     89/<- %esp 5/r32/ebp
26228     5d/pop-to-ebp
26229     c3/return
26230 
26231 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26232     # . prologue
26233     55/push-ebp
26234     89/<- %ebp 4/r32/esp
26235     # . save registers
26236     50/push-eax
26237     #
26238     (emit-indent *(ebp+8) *Curr-block-depth)
26239     (write-buffered *(ebp+8) "(copy-bytes")
26240     # eax = stmt
26241     8b/-> *(ebp+0xc) 0/r32/eax
26242     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
26243     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26244     (emit-subx-call-operand *(ebp+8) %eax)
26245     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
26246     (emit-subx-call-operand *(ebp+8) %eax)
26247     (write-buffered *(ebp+8) Space)
26248     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
26249     (write-int32-hex-buffered *(ebp+8) %eax)
26250     (write-buffered *(ebp+8) ")\n")
26251 $translate-mu-copy-object-stmt:end:
26252     # . restore registers
26253     58/pop-to-eax
26254     # . epilogue
26255     89/<- %esp 5/r32/ebp
26256     5d/pop-to-ebp
26257     c3/return
26258 
26259 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26260     # . prologue
26261     55/push-ebp
26262     89/<- %ebp 4/r32/esp
26263     # . save registers
26264     50/push-eax
26265     56/push-esi
26266     57/push-edi
26267     # esi = stmt
26268     8b/-> *(ebp+0xc) 6/r32/esi
26269     # var target/edi: (addr stmt-var) = stmt->inouts[0]
26270     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26271     89/<- %edi 0/r32/eax
26272     #
26273     (emit-indent *(ebp+8) *Curr-block-depth)
26274     (write-buffered *(ebp+8) "(allocate Heap ")
26275     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
26276     (write-int32-hex-buffered *(ebp+8) %eax)
26277     (emit-subx-call-operand *(ebp+8) %edi)
26278     (write-buffered *(ebp+8) ")\n")
26279 $translate-mu-allocate-stmt:end:
26280     # . restore registers
26281     5f/pop-to-edi
26282     5e/pop-to-esi
26283     58/pop-to-eax
26284     # . epilogue
26285     89/<- %esp 5/r32/ebp
26286     5d/pop-to-ebp
26287     c3/return
26288 
26289 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
26290     # . prologue
26291     55/push-ebp
26292     89/<- %ebp 4/r32/esp
26293     # var t/eax: (addr type-tree) = s->value->type
26294     8b/-> *(ebp+8) 0/r32/eax
26295     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26296     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26297     # TODO: check eax != 0
26298     # TODO: check !t->is-atom?
26299     # TODO: check t->left == addr
26300     # t = t->right
26301 $addr-handle-payload-size:skip-addr:
26302     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26303     # TODO: check eax != 0
26304     # TODO: check !t->is-atom?
26305     # TODO: check t->left == handle
26306     # t = t->right
26307 $addr-handle-payload-size:skip-handle:
26308     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26309     # TODO: check eax != 0
26310     # if !t->is-atom? t = t->left
26311     81 7/subop/compare *eax 0/imm32/false
26312     {
26313       75/jump-if-!= break/disp8
26314       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26315     }
26316     # TODO: check t->is-atom?
26317     # return size(t->value)
26318     (size-of-type-id *(eax+4))  # Type-tree-value => eax
26319 $addr-handle-payload-size:end:
26320     # . epilogue
26321     89/<- %esp 5/r32/ebp
26322     5d/pop-to-ebp
26323     c3/return
26324 
26325 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
26326     # . prologue
26327     55/push-ebp
26328     89/<- %ebp 4/r32/esp
26329     # var t/eax: (addr type-tree) = s->value->type
26330     8b/-> *(ebp+8) 0/r32/eax
26331     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26332     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26333     # TODO: check eax != 0
26334     # TODO: check !t->is-atom?
26335     # TODO: check t->left == addr
26336     # t = t->right
26337 $addr-payload-size:skip-addr:
26338     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26339     # TODO: check eax != 0
26340     # if !t->is-atom? t = t->left
26341     81 7/subop/compare *eax 0/imm32/false
26342     {
26343       75/jump-if-!= break/disp8
26344       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26345     }
26346     # TODO: check t->is-atom?
26347     # return size(t->value)
26348     (size-of-type-id *(eax+4))  # Type-tree-value => eax
26349 $addr-payload-size:end:
26350     # . epilogue
26351     89/<- %esp 5/r32/ebp
26352     5d/pop-to-ebp
26353     c3/return
26354 
26355 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26356     # . prologue
26357     55/push-ebp
26358     89/<- %ebp 4/r32/esp
26359     # . save registers
26360     50/push-eax
26361     51/push-ecx
26362     56/push-esi
26363     57/push-edi
26364     # esi = stmt
26365     8b/-> *(ebp+0xc) 6/r32/esi
26366     # var target/edi: (addr stmt-var) = stmt->inouts[0]
26367     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26368     89/<- %edi 0/r32/eax
26369     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
26370     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
26371     89/<- %ecx 0/r32/eax
26372     #
26373     (emit-indent *(ebp+8) *Curr-block-depth)
26374     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
26375     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
26376     (write-int32-hex-buffered *(ebp+8) %eax)
26377     (emit-subx-call-operand *(ebp+8) %ecx)
26378     (emit-subx-call-operand *(ebp+8) %edi)
26379     (write-buffered *(ebp+8) ")\n")
26380 $translate-mu-populate-stmt:end:
26381     # . restore registers
26382     5f/pop-to-edi
26383     5e/pop-to-esi
26384     59/pop-to-ecx
26385     58/pop-to-eax
26386     # . epilogue
26387     89/<- %esp 5/r32/ebp
26388     5d/pop-to-ebp
26389     c3/return
26390 
26391 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26392     # . prologue
26393     55/push-ebp
26394     89/<- %ebp 4/r32/esp
26395     # . save registers
26396     50/push-eax
26397     51/push-ecx
26398     56/push-esi
26399     57/push-edi
26400     # esi = stmt
26401     8b/-> *(ebp+0xc) 6/r32/esi
26402     # var target/edi: (addr stmt-var) = stmt->inouts[0]
26403     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26404     89/<- %edi 0/r32/eax
26405     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
26406     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
26407     89/<- %ecx 0/r32/eax
26408     #
26409     (emit-indent *(ebp+8) *Curr-block-depth)
26410     (write-buffered *(ebp+8) "(new-stream Heap ")
26411     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
26412     (write-int32-hex-buffered *(ebp+8) %eax)
26413     (emit-subx-call-operand *(ebp+8) %ecx)
26414     (emit-subx-call-operand *(ebp+8) %edi)
26415     (write-buffered *(ebp+8) ")\n")
26416 $translate-mu-populate-stream-stmt:end:
26417     # . restore registers
26418     5f/pop-to-edi
26419     5e/pop-to-esi
26420     59/pop-to-ecx
26421     58/pop-to-eax
26422     # . epilogue
26423     89/<- %esp 5/r32/ebp
26424     5d/pop-to-ebp
26425     c3/return
26426 
26427 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26428     # . prologue
26429     55/push-ebp
26430     89/<- %ebp 4/r32/esp
26431     # . save registers
26432     50/push-eax
26433     51/push-ecx
26434     56/push-esi
26435     57/push-edi
26436     # esi = stmt
26437     8b/-> *(ebp+0xc) 6/r32/esi
26438     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
26439     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26440     89/<- %ecx 0/r32/eax
26441     # var target/edi: (addr stmt-var) = stmt->inouts[1]
26442     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26443     89/<- %edi 0/r32/eax
26444     #
26445     (emit-indent *(ebp+8) *Curr-block-depth)
26446     (write-buffered *(ebp+8) "(read-from-stream")
26447     (emit-subx-call-operand *(ebp+8) %ecx)
26448     (emit-subx-call-operand *(ebp+8) %edi)
26449     (write-buffered *(ebp+8) Space)
26450     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
26451     (write-int32-hex-buffered *(ebp+8) %eax)
26452     (write-buffered *(ebp+8) ")\n")
26453 $translate-mu-read-from-stream-stmt:end:
26454     # . restore registers
26455     5f/pop-to-edi
26456     5e/pop-to-esi
26457     59/pop-to-ecx
26458     58/pop-to-eax
26459     # . epilogue
26460     89/<- %esp 5/r32/ebp
26461     5d/pop-to-ebp
26462     c3/return
26463 
26464 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26465     # . prologue
26466     55/push-ebp
26467     89/<- %ebp 4/r32/esp
26468     # . save registers
26469     50/push-eax
26470     51/push-ecx
26471     56/push-esi
26472     57/push-edi
26473     # esi = stmt
26474     8b/-> *(ebp+0xc) 6/r32/esi
26475     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
26476     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26477     89/<- %ecx 0/r32/eax
26478     # var target/edi: (addr stmt-var) = stmt->inouts[1]
26479     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26480     89/<- %edi 0/r32/eax
26481     #
26482     (emit-indent *(ebp+8) *Curr-block-depth)
26483     (write-buffered *(ebp+8) "(write-to-stream")
26484     (emit-subx-call-operand *(ebp+8) %ecx)
26485     (flush *(ebp+8))
26486     (emit-subx-call-operand *(ebp+8) %edi)
26487     (flush *(ebp+8))
26488     (write-buffered *(ebp+8) Space)
26489     (flush *(ebp+8))
26490     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
26491     (write-int32-hex-buffered *(ebp+8) %eax)
26492     (write-buffered *(ebp+8) ")\n")
26493 $translate-mu-write-to-stream-stmt:end:
26494     # . restore registers
26495     5f/pop-to-edi
26496     5e/pop-to-esi
26497     59/pop-to-ecx
26498     58/pop-to-eax
26499     # . epilogue
26500     89/<- %esp 5/r32/ebp
26501     5d/pop-to-ebp
26502     c3/return
26503 
26504 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
26505     # . prologue
26506     55/push-ebp
26507     89/<- %ebp 4/r32/esp
26508     # var t/eax: (addr type-tree) = s->value->type
26509     8b/-> *(ebp+8) 0/r32/eax
26510     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26511     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26512     # TODO: check eax != 0
26513     # TODO: check !t->is-atom?
26514     # TODO: check t->left == addr
26515     # t = t->right
26516 $addr-handle-array-payload-size:skip-addr:
26517     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26518     # TODO: check eax != 0
26519     # TODO: check !t->is-atom?
26520     # TODO: check t->left == handle
26521     # t = t->right
26522 $addr-handle-array-payload-size:skip-handle:
26523     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26524     # TODO: check eax != 0
26525     # TODO: check !t->is-atom?
26526     # TODO: check t->left == array
26527     # t = t->right
26528 $addr-handle-array-payload-size:skip-array:
26529     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26530     # TODO: check eax != 0
26531     # if !t->is-atom? t = t->left
26532     81 7/subop/compare *eax 0/imm32/false
26533     {
26534       75/jump-if-!= break/disp8
26535       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26536     }
26537 $addr-handle-array-payload-size:compute-size:
26538     # TODO: check t->is-atom?
26539     # return size(t->value)
26540     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
26541 $addr-handle-array-payload-size:end:
26542     # . epilogue
26543     89/<- %esp 5/r32/ebp
26544     5d/pop-to-ebp
26545     c3/return
26546 
26547 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
26548     # . prologue
26549     55/push-ebp
26550     89/<- %ebp 4/r32/esp
26551     # var t/eax: (addr type-tree) = s->value->type
26552     8b/-> *(ebp+8) 0/r32/eax
26553     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26554     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26555     # TODO: check eax != 0
26556     # TODO: check !t->is-atom?
26557     # TODO: check t->left == addr
26558     # t = t->right
26559 $addr-handle-stream-payload-size:skip-addr:
26560     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26561     # TODO: check eax != 0
26562     # TODO: check !t->is-atom?
26563     # TODO: check t->left == handle
26564     # t = t->right
26565 $addr-handle-stream-payload-size:skip-handle:
26566     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26567     # TODO: check eax != 0
26568     # TODO: check !t->is-atom?
26569     # TODO: check t->left == stream
26570     # t = t->right
26571 $addr-handle-stream-payload-size:skip-stream:
26572     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26573     # TODO: check eax != 0
26574     # if !t->is-atom? t = t->left
26575     81 7/subop/compare *eax 0/imm32/false
26576     {
26577       75/jump-if-!= break/disp8
26578       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26579     }
26580 $addr-handle-stream-payload-size:compute-size:
26581     # TODO: check t->is-atom?
26582     # return size(t->value)
26583     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
26584 $addr-handle-stream-payload-size:end:
26585     # . epilogue
26586     89/<- %esp 5/r32/ebp
26587     5d/pop-to-ebp
26588     c3/return
26589 
26590 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
26591     # precondition: n is positive
26592     # . prologue
26593     55/push-ebp
26594     89/<- %ebp 4/r32/esp
26595     # eax = n
26596     8b/-> *(ebp+8) 0/r32/eax
26597     # if (n < 0) abort
26598     3d/compare-eax-with 0/imm32
26599     0f 8c/jump-if-< $power-of-2?:abort/disp32
26600     # var tmp/eax: int = n-1
26601     48/decrement-eax
26602     # var tmp2/eax: int = n & tmp
26603     23/and-> *(ebp+8) 0/r32/eax
26604     # return (tmp2 == 0)
26605     3d/compare-eax-and 0/imm32
26606     0f 94/set-byte-if-= %al
26607     81 4/subop/and %eax 0xff/imm32
26608 $power-of-2?:end:
26609     # . epilogue
26610     89/<- %esp 5/r32/ebp
26611     5d/pop-to-ebp
26612     c3/return
26613 
26614 $power-of-2?:abort:
26615     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
26616     (flush *(ebp+0xc))
26617     (stop *(ebp+0x10) 1)
26618     # never gets here
26619 
26620 num-shift-rights:  # n: int -> result/eax: int
26621     # precondition: n is a positive power of 2
26622     # . prologue
26623     55/push-ebp
26624     89/<- %ebp 4/r32/esp
26625     # . save registers
26626     51/push-ecx
26627     # var curr/ecx: int = n
26628     8b/-> *(ebp+8) 1/r32/ecx
26629     # result = 0
26630     b8/copy-to-eax 0/imm32
26631     {
26632       # if (curr <= 1) break
26633       81 7/subop/compare %ecx 1/imm32
26634       7e/jump-if-<= break/disp8
26635       40/increment-eax
26636       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
26637       eb/jump loop/disp8
26638     }
26639 $num-shift-rights:end:
26640     # . restore registers
26641     59/pop-to-ecx
26642     # . epilogue
26643     89/<- %esp 5/r32/ebp
26644     5d/pop-to-ebp
26645     c3/return
26646 
26647 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
26648     # . prologue
26649     55/push-ebp
26650     89/<- %ebp 4/r32/esp
26651     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
26652     8b/-> *(ebp+8) 0/r32/eax
26653     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26654     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
26655     # var output-var/eax: (addr var) = second-inout->value
26656     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26657 #?     (write-buffered Stderr "mu-get-offset: ")
26658 #?     (write-int32-hex-buffered Stderr %eax)
26659 #?     (write-buffered Stderr " name: ")
26660 #?     50/push-eax
26661 #?     (lookup *eax *(eax+4))  # Var-name
26662 #?     (write-buffered Stderr %eax)
26663 #?     58/pop-to-eax
26664 #?     (write-buffered Stderr Newline)
26665 #?     (flush Stderr)
26666     # return output-var->stack-offset
26667     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
26668 #?     (write-buffered Stderr "=> ")
26669 #?     (write-int32-hex-buffered Stderr %eax)
26670 #?     (write-buffered Stderr Newline)
26671 #?     (flush Stderr)
26672 $emit-get-offset:end:
26673     # . epilogue
26674     89/<- %esp 5/r32/ebp
26675     5d/pop-to-ebp
26676     c3/return
26677 
26678 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)
26679     # . prologue
26680     55/push-ebp
26681     89/<- %ebp 4/r32/esp
26682     # . save registers
26683     50/push-eax
26684     51/push-ecx
26685     56/push-esi
26686     # esi = block
26687     8b/-> *(ebp+0xc) 6/r32/esi
26688     # block->var->block-depth = *Curr-block-depth
26689     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
26690     8b/-> *Curr-block-depth 1/r32/ecx
26691     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
26692     # var stmts/eax: (addr list stmt) = lookup(block->statements)
26693     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
26694     #
26695     {
26696 $emit-subx-block:check-empty:
26697       3d/compare-eax-and 0/imm32
26698       0f 84/jump-if-= break/disp32
26699       (emit-indent *(ebp+8) *Curr-block-depth)
26700       (write-buffered *(ebp+8) "{\n")
26701       # var v/ecx: (addr var) = lookup(block->var)
26702       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
26703       89/<- %ecx 0/r32/eax
26704       #
26705       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
26706       (write-buffered *(ebp+8) %eax)
26707       (write-buffered *(ebp+8) ":loop:\n")
26708       ff 0/subop/increment *Curr-block-depth
26709       (push *(ebp+0x10) *(esi+0xc))  # Block-var
26710       (push *(ebp+0x10) *(esi+0x10))  # Block-var
26711       (push *(ebp+0x10) 0)  # false
26712       # emit block->statements
26713       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
26714       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
26715       (pop *(ebp+0x10))  # => eax
26716       (pop *(ebp+0x10))  # => eax
26717       (pop *(ebp+0x10))  # => eax
26718       ff 1/subop/decrement *Curr-block-depth
26719       (emit-indent *(ebp+8) *Curr-block-depth)
26720       (write-buffered *(ebp+8) "}\n")
26721       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
26722       (write-buffered *(ebp+8) %eax)
26723       (write-buffered *(ebp+8) ":break:\n")
26724     }
26725 $emit-subx-block:end:
26726     # . restore registers
26727     5e/pop-to-esi
26728     59/pop-to-ecx
26729     58/pop-to-eax
26730     # . epilogue
26731     89/<- %esp 5/r32/ebp
26732     5d/pop-to-ebp
26733     c3/return
26734 
26735 # Primitives supported
26736 # See mu_instructions for a summary of this linked-list data structure.
26737 #
26738 # For each operation, put variants with hard-coded registers before flexible ones.
26739 #
26740 # Unfortunately, our restrictions on addresses require that various fields in
26741 # primitives be handles, which complicates these definitions.
26742 #   - we need to insert dummy fields all over the place for fake alloc-ids
26743 #   - we can't use our syntax sugar of quoted literals for string fields
26744 #
26745 # Fake alloc-ids are needed because our type definitions up top require
26746 # handles but it's clearer to statically allocate these long-lived objects.
26747 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
26748 #
26749 # Every 'object' below starts with a fake alloc-id. It may also contain other
26750 # fake alloc-ids for various handle fields.
26751 #
26752 # I think of objects starting with a fake alloc-id as having type 'payload'.
26753 # It's not really intended to be created dynamically; for that use `allocate`
26754 # as usual.
26755 #
26756 # Idea for a notation to simplify such definitions:
26757 #   _Primitive-increment-eax:  # (payload primitive)
26758 #     0x11/alloc-id:fake:payload
26759 #     0x11 @(0x11 "increment")  # name
26760 #     0 0                       # inouts
26761 #     0x11 @(0x11/payload
26762 #            0x11 @(0x11/payload  # List-value
26763 #                   0 0             # Var-name
26764 #                   0x11 @(0x11     # Var-type
26765 #                          1/is-atom
26766 #                          1/value 0/unused   # Type-tree-left
26767 #                          0 0                # Type-tree-right
26768 #                         )
26769 #                   1               # block-depth
26770 #                   0               # stack-offset
26771 #                   0x11 @(0x11 "eax")  # Var-register
26772 #                  )
26773 #            0 0)                 # List-next
26774 #     ...
26775 #     _Primitive-increment-ecx/imm32/next
26776 #   ...
26777 # Awfully complex and non-obvious. But also clearly signals there's something
26778 # to learn here, so may be worth trying.
26779 #
26780 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
26781 #
26782 # For now we'll continue to just use comments and manually ensure they stay up
26783 # to date.
26784 == data
26785 Primitives:  # (addr primitive)
26786 # - increment/decrement
26787 _Primitive-increment-eax:  # (addr primitive)
26788     # var/eax <- increment => 40/increment-eax
26789     0x11/imm32/alloc-id:fake
26790     _string-increment/imm32/name
26791     0/imm32/no-inouts
26792     0/imm32/no-inouts
26793     0x11/imm32/alloc-id:fake
26794     Single-int-var-in-eax/imm32/outputs
26795     0x11/imm32/alloc-id:fake
26796     _string_40_increment_eax/imm32/subx-name
26797     0/imm32/no-rm32
26798     0/imm32/no-r32
26799     0/imm32/no-imm32
26800     0/imm32/no-imm8
26801     0/imm32/no-disp32
26802     0/imm32/no-xm32
26803     0/imm32/no-x32
26804     0x11/imm32/alloc-id:fake
26805     _Primitive-increment-ecx/imm32/next
26806 _Primitive-increment-ecx:  # (payload primitive)
26807     0x11/imm32/alloc-id:fake:payload
26808     # var/ecx <- increment => 41/increment-ecx
26809     0x11/imm32/alloc-id:fake
26810     _string-increment/imm32/name
26811     0/imm32/no-inouts
26812     0/imm32/no-inouts
26813     0x11/imm32/alloc-id:fake
26814     Single-int-var-in-ecx/imm32/outputs
26815     0x11/imm32/alloc-id:fake
26816     _string_41_increment_ecx/imm32/subx-name
26817     0/imm32/no-rm32
26818     0/imm32/no-r32
26819     0/imm32/no-imm32
26820     0/imm32/no-imm8
26821     0/imm32/no-disp32
26822     0/imm32/no-xm32
26823     0/imm32/no-x32
26824     0x11/imm32/alloc-id:fake
26825     _Primitive-increment-edx/imm32/next
26826 _Primitive-increment-edx:  # (payload primitive)
26827     0x11/imm32/alloc-id:fake:payload
26828     # var/edx <- increment => 42/increment-edx
26829     0x11/imm32/alloc-id:fake
26830     _string-increment/imm32/name
26831     0/imm32/no-inouts
26832     0/imm32/no-inouts
26833     0x11/imm32/alloc-id:fake
26834     Single-int-var-in-edx/imm32/outputs
26835     0x11/imm32/alloc-id:fake
26836     _string_42_increment_edx/imm32/subx-name
26837     0/imm32/no-rm32
26838     0/imm32/no-r32
26839     0/imm32/no-imm32
26840     0/imm32/no-imm8
26841     0/imm32/no-disp32
26842     0/imm32/no-xm32
26843     0/imm32/no-x32
26844     0x11/imm32/alloc-id:fake
26845     _Primitive-increment-ebx/imm32/next
26846 _Primitive-increment-ebx:  # (payload primitive)
26847     0x11/imm32/alloc-id:fake:payload
26848     # var/ebx <- increment => 43/increment-ebx
26849     0x11/imm32/alloc-id:fake
26850     _string-increment/imm32/name
26851     0/imm32/no-inouts
26852     0/imm32/no-inouts
26853     0x11/imm32/alloc-id:fake
26854     Single-int-var-in-ebx/imm32/outputs
26855     0x11/imm32/alloc-id:fake
26856     _string_43_increment_ebx/imm32/subx-name
26857     0/imm32/no-rm32
26858     0/imm32/no-r32
26859     0/imm32/no-imm32
26860     0/imm32/no-imm8
26861     0/imm32/no-disp32
26862     0/imm32/no-xm32
26863     0/imm32/no-x32
26864     0x11/imm32/alloc-id:fake
26865     _Primitive-increment-esi/imm32/next
26866 _Primitive-increment-esi:  # (payload primitive)
26867     0x11/imm32/alloc-id:fake:payload
26868     # var/esi <- increment => 46/increment-esi
26869     0x11/imm32/alloc-id:fake
26870     _string-increment/imm32/name
26871     0/imm32/no-inouts
26872     0/imm32/no-inouts
26873     0x11/imm32/alloc-id:fake
26874     Single-int-var-in-esi/imm32/outputs
26875     0x11/imm32/alloc-id:fake
26876     _string_46_increment_esi/imm32/subx-name
26877     0/imm32/no-rm32
26878     0/imm32/no-r32
26879     0/imm32/no-imm32
26880     0/imm32/no-imm8
26881     0/imm32/no-disp32
26882     0/imm32/no-xm32
26883     0/imm32/no-x32
26884     0x11/imm32/alloc-id:fake
26885     _Primitive-increment-edi/imm32/next
26886 _Primitive-increment-edi:  # (payload primitive)
26887     0x11/imm32/alloc-id:fake:payload
26888     # var/edi <- increment => 47/increment-edi
26889     0x11/imm32/alloc-id:fake
26890     _string-increment/imm32/name
26891     0/imm32/no-inouts
26892     0/imm32/no-inouts
26893     0x11/imm32/alloc-id:fake
26894     Single-int-var-in-edi/imm32/outputs
26895     0x11/imm32/alloc-id:fake
26896     _string_47_increment_edi/imm32/subx-name
26897     0/imm32/no-rm32
26898     0/imm32/no-r32
26899     0/imm32/no-imm32
26900     0/imm32/no-imm8
26901     0/imm32/no-disp32
26902     0/imm32/no-xm32
26903     0/imm32/no-x32
26904     0x11/imm32/alloc-id:fake
26905     _Primitive-decrement-eax/imm32/next
26906 _Primitive-decrement-eax:  # (payload primitive)
26907     0x11/imm32/alloc-id:fake:payload
26908     # var/eax <- decrement => 48/decrement-eax
26909     0x11/imm32/alloc-id:fake
26910     _string-decrement/imm32/name
26911     0/imm32/no-inouts
26912     0/imm32/no-inouts
26913     0x11/imm32/alloc-id:fake
26914     Single-int-var-in-eax/imm32/outputs
26915     0x11/imm32/alloc-id:fake
26916     _string_48_decrement_eax/imm32/subx-name
26917     0/imm32/no-rm32
26918     0/imm32/no-r32
26919     0/imm32/no-imm32
26920     0/imm32/no-imm8
26921     0/imm32/no-disp32
26922     0/imm32/no-xm32
26923     0/imm32/no-x32
26924     0x11/imm32/alloc-id:fake
26925     _Primitive-decrement-ecx/imm32/next
26926 _Primitive-decrement-ecx:  # (payload primitive)
26927     0x11/imm32/alloc-id:fake:payload
26928     # var/ecx <- decrement => 49/decrement-ecx
26929     0x11/imm32/alloc-id:fake
26930     _string-decrement/imm32/name
26931     0/imm32/no-inouts
26932     0/imm32/no-inouts
26933     0x11/imm32/alloc-id:fake
26934     Single-int-var-in-ecx/imm32/outputs
26935     0x11/imm32/alloc-id:fake
26936     _string_49_decrement_ecx/imm32/subx-name
26937     0/imm32/no-rm32
26938     0/imm32/no-r32
26939     0/imm32/no-imm32
26940     0/imm32/no-imm8
26941     0/imm32/no-disp32
26942     0/imm32/no-xm32
26943     0/imm32/no-x32
26944     0x11/imm32/alloc-id:fake
26945     _Primitive-decrement-edx/imm32/next
26946 _Primitive-decrement-edx:  # (payload primitive)
26947     0x11/imm32/alloc-id:fake:payload
26948     # var/edx <- decrement => 4a/decrement-edx
26949     0x11/imm32/alloc-id:fake
26950     _string-decrement/imm32/name
26951     0/imm32/no-inouts
26952     0/imm32/no-inouts
26953     0x11/imm32/alloc-id:fake
26954     Single-int-var-in-edx/imm32/outputs
26955     0x11/imm32/alloc-id:fake
26956     _string_4a_decrement_edx/imm32/subx-name
26957     0/imm32/no-rm32
26958     0/imm32/no-r32
26959     0/imm32/no-imm32
26960     0/imm32/no-imm8
26961     0/imm32/no-disp32
26962     0/imm32/no-xm32
26963     0/imm32/no-x32
26964     0x11/imm32/alloc-id:fake
26965     _Primitive-decrement-ebx/imm32/next
26966 _Primitive-decrement-ebx:  # (payload primitive)
26967     0x11/imm32/alloc-id:fake:payload
26968     # var/ebx <- decrement => 4b/decrement-ebx
26969     0x11/imm32/alloc-id:fake
26970     _string-decrement/imm32/name
26971     0/imm32/no-inouts
26972     0/imm32/no-inouts
26973     0x11/imm32/alloc-id:fake
26974     Single-int-var-in-ebx/imm32/outputs
26975     0x11/imm32/alloc-id:fake
26976     _string_4b_decrement_ebx/imm32/subx-name
26977     0/imm32/no-rm32
26978     0/imm32/no-r32
26979     0/imm32/no-imm32
26980     0/imm32/no-imm8
26981     0/imm32/no-disp32
26982     0/imm32/no-xm32
26983     0/imm32/no-x32
26984     0x11/imm32/alloc-id:fake
26985     _Primitive-decrement-esi/imm32/next
26986 _Primitive-decrement-esi:  # (payload primitive)
26987     0x11/imm32/alloc-id:fake:payload
26988     # var/esi <- decrement => 4e/decrement-esi
26989     0x11/imm32/alloc-id:fake
26990     _string-decrement/imm32/name
26991     0/imm32/no-inouts
26992     0/imm32/no-inouts
26993     0x11/imm32/alloc-id:fake
26994     Single-int-var-in-esi/imm32/outputs
26995     0x11/imm32/alloc-id:fake
26996     _string_4e_decrement_esi/imm32/subx-name
26997     0/imm32/no-rm32
26998     0/imm32/no-r32
26999     0/imm32/no-imm32
27000     0/imm32/no-imm8
27001     0/imm32/no-disp32
27002     0/imm32/no-xm32
27003     0/imm32/no-x32
27004     0x11/imm32/alloc-id:fake
27005     _Primitive-decrement-edi/imm32/next
27006 _Primitive-decrement-edi:  # (payload primitive)
27007     0x11/imm32/alloc-id:fake:payload
27008     # var/edi <- decrement => 4f/decrement-edi
27009     0x11/imm32/alloc-id:fake
27010     _string-decrement/imm32/name
27011     0/imm32/no-inouts
27012     0/imm32/no-inouts
27013     0x11/imm32/alloc-id:fake
27014     Single-int-var-in-edi/imm32/outputs
27015     0x11/imm32/alloc-id:fake
27016     _string_4f_decrement_edi/imm32/subx-name
27017     0/imm32/no-rm32
27018     0/imm32/no-r32
27019     0/imm32/no-imm32
27020     0/imm32/no-imm8
27021     0/imm32/no-disp32
27022     0/imm32/no-xm32
27023     0/imm32/no-x32
27024     0x11/imm32/alloc-id:fake
27025     _Primitive-increment-mem/imm32/next
27026 _Primitive-increment-mem:  # (payload primitive)
27027     0x11/imm32/alloc-id:fake:payload
27028     # increment var => ff 0/subop/increment *(ebp+__)
27029     0x11/imm32/alloc-id:fake
27030     _string-increment/imm32/name
27031     0x11/imm32/alloc-id:fake
27032     Single-int-var-in-mem/imm32/inouts
27033     0/imm32/no-outputs
27034     0/imm32/no-outputs
27035     0x11/imm32/alloc-id:fake
27036     _string_ff_subop_increment/imm32/subx-name
27037     1/imm32/rm32-is-first-inout
27038     0/imm32/no-r32
27039     0/imm32/no-imm32
27040     0/imm32/no-imm8
27041     0/imm32/no-disp32
27042     0/imm32/no-xm32
27043     0/imm32/no-x32
27044     0x11/imm32/alloc-id:fake
27045     _Primitive-increment-reg/imm32/next
27046 _Primitive-increment-reg:  # (payload primitive)
27047     0x11/imm32/alloc-id:fake:payload
27048     # var/reg <- increment => ff 0/subop/increment %__
27049     0x11/imm32/alloc-id:fake
27050     _string-increment/imm32/name
27051     0/imm32/no-inouts
27052     0/imm32/no-inouts
27053     0x11/imm32/alloc-id:fake
27054     Single-int-var-in-some-register/imm32/outputs
27055     0x11/imm32/alloc-id:fake
27056     _string_ff_subop_increment/imm32/subx-name
27057     3/imm32/rm32-is-first-output
27058     0/imm32/no-r32
27059     0/imm32/no-imm32
27060     0/imm32/no-imm8
27061     0/imm32/no-disp32
27062     0/imm32/no-xm32
27063     0/imm32/no-x32
27064     0x11/imm32/alloc-id:fake
27065     _Primitive-decrement-mem/imm32/next
27066 _Primitive-decrement-mem:  # (payload primitive)
27067     0x11/imm32/alloc-id:fake:payload
27068     # decrement var => ff 1/subop/decrement *(ebp+__)
27069     0x11/imm32/alloc-id:fake
27070     _string-decrement/imm32/name
27071     0x11/imm32/alloc-id:fake
27072     Single-int-var-in-mem/imm32/inouts
27073     0/imm32/no-outputs
27074     0/imm32/no-outputs
27075     0x11/imm32/alloc-id:fake
27076     _string_ff_subop_decrement/imm32/subx-name
27077     1/imm32/rm32-is-first-inout
27078     0/imm32/no-r32
27079     0/imm32/no-imm32
27080     0/imm32/no-imm8
27081     0/imm32/no-disp32
27082     0/imm32/no-xm32
27083     0/imm32/no-x32
27084     0x11/imm32/alloc-id:fake
27085     _Primitive-decrement-reg/imm32/next
27086 _Primitive-decrement-reg:  # (payload primitive)
27087     0x11/imm32/alloc-id:fake:payload
27088     # var/reg <- decrement => ff 1/subop/decrement %__
27089     0x11/imm32/alloc-id:fake
27090     _string-decrement/imm32/name
27091     0/imm32/no-inouts
27092     0/imm32/no-inouts
27093     0x11/imm32/alloc-id:fake
27094     Single-int-var-in-some-register/imm32/outputs
27095     0x11/imm32/alloc-id:fake
27096     _string_ff_subop_decrement/imm32/subx-name
27097     3/imm32/rm32-is-first-output
27098     0/imm32/no-r32
27099     0/imm32/no-imm32
27100     0/imm32/no-imm8
27101     0/imm32/no-disp32
27102     0/imm32/no-xm32
27103     0/imm32/no-x32
27104     0x11/imm32/alloc-id:fake
27105     _Primitive-add-to-eax/imm32/next
27106 # - add
27107 _Primitive-add-to-eax:  # (payload primitive)
27108     0x11/imm32/alloc-id:fake:payload
27109     # var/eax <- add lit => 05/add-to-eax lit/imm32
27110     0x11/imm32/alloc-id:fake
27111     _string-add/imm32/name
27112     0x11/imm32/alloc-id:fake
27113     Single-lit-var/imm32/inouts
27114     0x11/imm32/alloc-id:fake
27115     Single-int-var-in-eax/imm32/outputs
27116     0x11/imm32/alloc-id:fake
27117     _string_05_add_to_eax/imm32/subx-name
27118     0/imm32/no-rm32
27119     0/imm32/no-r32
27120     1/imm32/imm32-is-first-inout
27121     0/imm32/no-imm8
27122     0/imm32/no-disp32
27123     0/imm32/no-xm32
27124     0/imm32/no-x32
27125     0x11/imm32/alloc-id:fake
27126     _Primitive-add-reg-to-reg/imm32/next
27127 _Primitive-add-reg-to-reg:  # (payload primitive)
27128     0x11/imm32/alloc-id:fake:payload
27129     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
27130     0x11/imm32/alloc-id:fake
27131     _string-add/imm32/name
27132     0x11/imm32/alloc-id:fake
27133     Single-int-var-in-some-register/imm32/inouts
27134     0x11/imm32/alloc-id:fake
27135     Single-int-var-in-some-register/imm32/outputs
27136     0x11/imm32/alloc-id:fake
27137     _string_01_add_to/imm32/subx-name
27138     3/imm32/rm32-is-first-output
27139     1/imm32/r32-is-first-inout
27140     0/imm32/no-imm32
27141     0/imm32/no-imm8
27142     0/imm32/no-disp32
27143     0/imm32/no-xm32
27144     0/imm32/no-x32
27145     0x11/imm32/alloc-id:fake
27146     _Primitive-add-reg-to-mem/imm32/next
27147 _Primitive-add-reg-to-mem:  # (payload primitive)
27148     0x11/imm32/alloc-id:fake:payload
27149     # add-to var1 var2/reg => 01/add-to var1 var2/r32
27150     0x11/imm32/alloc-id:fake
27151     _string-add-to/imm32/name
27152     0x11/imm32/alloc-id:fake
27153     Two-args-int-stack-int-reg/imm32/inouts
27154     0/imm32/no-outputs
27155     0/imm32/no-outputs
27156     0x11/imm32/alloc-id:fake
27157     _string_01_add_to/imm32/subx-name
27158     1/imm32/rm32-is-first-inout
27159     2/imm32/r32-is-second-inout
27160     0/imm32/no-imm32
27161     0/imm32/no-imm8
27162     0/imm32/no-disp32
27163     0/imm32/no-xm32
27164     0/imm32/no-x32
27165     0x11/imm32/alloc-id:fake
27166     _Primitive-add-mem-to-reg/imm32/next
27167 _Primitive-add-mem-to-reg:  # (payload primitive)
27168     0x11/imm32/alloc-id:fake:payload
27169     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
27170     0x11/imm32/alloc-id:fake
27171     _string-add/imm32/name
27172     0x11/imm32/alloc-id:fake
27173     Single-int-var-in-mem/imm32/inouts
27174     0x11/imm32/alloc-id:fake
27175     Single-int-var-in-some-register/imm32/outputs
27176     0x11/imm32/alloc-id:fake
27177     _string_03_add/imm32/subx-name
27178     1/imm32/rm32-is-first-inout
27179     3/imm32/r32-is-first-output
27180     0/imm32/no-imm32
27181     0/imm32/no-imm8
27182     0/imm32/no-disp32
27183     0/imm32/no-xm32
27184     0/imm32/no-x32
27185     0x11/imm32/alloc-id:fake
27186     _Primitive-add-lit-to-reg/imm32/next
27187 _Primitive-add-lit-to-reg:  # (payload primitive)
27188     0x11/imm32/alloc-id:fake:payload
27189     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
27190     0x11/imm32/alloc-id:fake
27191     _string-add/imm32/name
27192     0x11/imm32/alloc-id:fake
27193     Single-lit-var/imm32/inouts
27194     0x11/imm32/alloc-id:fake
27195     Single-int-var-in-some-register/imm32/outputs
27196     0x11/imm32/alloc-id:fake
27197     _string_81_subop_add/imm32/subx-name
27198     3/imm32/rm32-is-first-output
27199     0/imm32/no-r32
27200     1/imm32/imm32-is-first-inout
27201     0/imm32/no-imm8
27202     0/imm32/no-disp32
27203     0/imm32/no-xm32
27204     0/imm32/no-x32
27205     0x11/imm32/alloc-id:fake
27206     _Primitive-add-lit-to-mem/imm32/next
27207 _Primitive-add-lit-to-mem:  # (payload primitive)
27208     0x11/imm32/alloc-id:fake:payload
27209     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
27210     0x11/imm32/alloc-id:fake
27211     _string-add-to/imm32/name
27212     0x11/imm32/alloc-id:fake
27213     Int-var-and-literal/imm32/inouts
27214     0/imm32/no-outputs
27215     0/imm32/no-outputs
27216     0x11/imm32/alloc-id:fake
27217     _string_81_subop_add/imm32/subx-name
27218     1/imm32/rm32-is-first-inout
27219     0/imm32/no-r32
27220     2/imm32/imm32-is-second-inout
27221     0/imm32/no-imm8
27222     0/imm32/no-disp32
27223     0/imm32/no-xm32
27224     0/imm32/no-x32
27225     0x11/imm32/alloc-id:fake
27226     _Primitive-subtract-from-eax/imm32/next
27227 # - subtract
27228 _Primitive-subtract-from-eax:  # (payload primitive)
27229     0x11/imm32/alloc-id:fake:payload
27230     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
27231     0x11/imm32/alloc-id:fake
27232     _string-subtract/imm32/name
27233     0x11/imm32/alloc-id:fake
27234     Single-lit-var/imm32/inouts
27235     0x11/imm32/alloc-id:fake
27236     Single-int-var-in-eax/imm32/outputs
27237     0x11/imm32/alloc-id:fake
27238     _string_2d_subtract_from_eax/imm32/subx-name
27239     0/imm32/no-rm32
27240     0/imm32/no-r32
27241     1/imm32/imm32-is-first-inout
27242     0/imm32/no-imm8
27243     0/imm32/no-disp32
27244     0/imm32/no-xm32
27245     0/imm32/no-x32
27246     0x11/imm32/alloc-id:fake
27247     _Primitive-subtract-reg-from-reg/imm32/next
27248 _Primitive-subtract-reg-from-reg:  # (payload primitive)
27249     0x11/imm32/alloc-id:fake:payload
27250     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
27251     0x11/imm32/alloc-id:fake
27252     _string-subtract/imm32/name
27253     0x11/imm32/alloc-id:fake
27254     Single-int-var-in-some-register/imm32/inouts
27255     0x11/imm32/alloc-id:fake
27256     Single-int-var-in-some-register/imm32/outputs
27257     0x11/imm32/alloc-id:fake
27258     _string_29_subtract_from/imm32/subx-name
27259     3/imm32/rm32-is-first-output
27260     1/imm32/r32-is-first-inout
27261     0/imm32/no-imm32
27262     0/imm32/no-imm8
27263     0/imm32/no-disp32
27264     0/imm32/no-xm32
27265     0/imm32/no-x32
27266     0x11/imm32/alloc-id:fake
27267     _Primitive-subtract-reg-from-mem/imm32/next
27268 _Primitive-subtract-reg-from-mem:  # (payload primitive)
27269     0x11/imm32/alloc-id:fake:payload
27270     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
27271     0x11/imm32/alloc-id:fake
27272     _string-subtract-from/imm32/name
27273     0x11/imm32/alloc-id:fake
27274     Two-args-int-stack-int-reg/imm32/inouts
27275     0/imm32/no-outputs
27276     0/imm32/no-outputs
27277     0x11/imm32/alloc-id:fake
27278     _string_29_subtract_from/imm32/subx-name
27279     1/imm32/rm32-is-first-inout
27280     2/imm32/r32-is-second-inout
27281     0/imm32/no-imm32
27282     0/imm32/no-imm8
27283     0/imm32/no-disp32
27284     0/imm32/no-xm32
27285     0/imm32/no-x32
27286     0x11/imm32/alloc-id:fake
27287     _Primitive-subtract-mem-from-reg/imm32/next
27288 _Primitive-subtract-mem-from-reg:  # (payload primitive)
27289     0x11/imm32/alloc-id:fake:payload
27290     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
27291     0x11/imm32/alloc-id:fake
27292     _string-subtract/imm32/name
27293     0x11/imm32/alloc-id:fake
27294     Single-int-var-in-mem/imm32/inouts
27295     0x11/imm32/alloc-id:fake
27296     Single-int-var-in-some-register/imm32/outputs
27297     0x11/imm32/alloc-id:fake
27298     _string_2b_subtract/imm32/subx-name
27299     1/imm32/rm32-is-first-inout
27300     3/imm32/r32-is-first-output
27301     0/imm32/no-imm32
27302     0/imm32/no-imm8
27303     0/imm32/no-disp32
27304     0/imm32/no-xm32
27305     0/imm32/no-x32
27306     0x11/imm32/alloc-id:fake
27307     _Primitive-subtract-lit-from-reg/imm32/next
27308 _Primitive-subtract-lit-from-reg:  # (payload primitive)
27309     0x11/imm32/alloc-id:fake:payload
27310     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
27311     0x11/imm32/alloc-id:fake
27312     _string-subtract/imm32/name
27313     0x11/imm32/alloc-id:fake
27314     Single-lit-var/imm32/inouts
27315     0x11/imm32/alloc-id:fake
27316     Single-int-var-in-some-register/imm32/outputs
27317     0x11/imm32/alloc-id:fake
27318     _string_81_subop_subtract/imm32/subx-name
27319     3/imm32/rm32-is-first-output
27320     0/imm32/no-r32
27321     1/imm32/imm32-is-first-inout
27322     0/imm32/no-imm8
27323     0/imm32/no-disp32
27324     0/imm32/no-xm32
27325     0/imm32/no-x32
27326     0x11/imm32/alloc-id:fake
27327     _Primitive-subtract-lit-from-mem/imm32/next
27328 _Primitive-subtract-lit-from-mem:  # (payload primitive)
27329     0x11/imm32/alloc-id:fake:payload
27330     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
27331     0x11/imm32/alloc-id:fake
27332     _string-subtract-from/imm32/name
27333     0x11/imm32/alloc-id:fake
27334     Int-var-and-literal/imm32/inouts
27335     0/imm32/no-outputs
27336     0/imm32/no-outputs
27337     0x11/imm32/alloc-id:fake
27338     _string_81_subop_subtract/imm32/subx-name
27339     1/imm32/rm32-is-first-inout
27340     0/imm32/no-r32
27341     2/imm32/imm32-is-second-inout
27342     0/imm32/no-imm8
27343     0/imm32/no-disp32
27344     0/imm32/no-xm32
27345     0/imm32/no-x32
27346     0x11/imm32/alloc-id:fake
27347     _Primitive-and-with-eax/imm32/next
27348 # - and
27349 _Primitive-and-with-eax:  # (payload primitive)
27350     0x11/imm32/alloc-id:fake:payload
27351     # var/eax <- and lit => 25/and-with-eax lit/imm32
27352     0x11/imm32/alloc-id:fake
27353     _string-and/imm32/name
27354     0x11/imm32/alloc-id:fake
27355     Single-lit-var/imm32/inouts
27356     0x11/imm32/alloc-id:fake
27357     Single-int-var-in-eax/imm32/outputs
27358     0x11/imm32/alloc-id:fake
27359     _string_25_and_with_eax/imm32/subx-name
27360     0/imm32/no-rm32
27361     0/imm32/no-r32
27362     1/imm32/imm32-is-first-inout
27363     0/imm32/no-imm8
27364     0/imm32/no-disp32
27365     0/imm32/no-xm32
27366     0/imm32/no-x32
27367     0x11/imm32/alloc-id:fake
27368     _Primitive-and-reg-with-reg/imm32/next
27369 _Primitive-and-reg-with-reg:  # (payload primitive)
27370     0x11/imm32/alloc-id:fake:payload
27371     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
27372     0x11/imm32/alloc-id:fake
27373     _string-and/imm32/name
27374     0x11/imm32/alloc-id:fake
27375     Single-int-var-in-some-register/imm32/inouts
27376     0x11/imm32/alloc-id:fake
27377     Single-int-var-in-some-register/imm32/outputs
27378     0x11/imm32/alloc-id:fake
27379     _string_21_and_with/imm32/subx-name
27380     3/imm32/rm32-is-first-output
27381     1/imm32/r32-is-first-inout
27382     0/imm32/no-imm32
27383     0/imm32/no-imm8
27384     0/imm32/no-disp32
27385     0/imm32/no-xm32
27386     0/imm32/no-x32
27387     0x11/imm32/alloc-id:fake
27388     _Primitive-and-reg-with-mem/imm32/next
27389 _Primitive-and-reg-with-mem:  # (payload primitive)
27390     0x11/imm32/alloc-id:fake:payload
27391     # and-with var1 var2/reg => 21/and-with var1 var2/r32
27392     0x11/imm32/alloc-id:fake
27393     _string-and-with/imm32/name
27394     0x11/imm32/alloc-id:fake
27395     Two-args-int-stack-int-reg/imm32/inouts
27396     0/imm32/no-outputs
27397     0/imm32/no-outputs
27398     0x11/imm32/alloc-id:fake
27399     _string_21_and_with/imm32/subx-name
27400     1/imm32/rm32-is-first-inout
27401     2/imm32/r32-is-second-inout
27402     0/imm32/no-imm32
27403     0/imm32/no-imm8
27404     0/imm32/no-disp32
27405     0/imm32/no-xm32
27406     0/imm32/no-x32
27407     0x11/imm32/alloc-id:fake
27408     _Primitive-and-mem-with-reg/imm32/next
27409 _Primitive-and-mem-with-reg:  # (payload primitive)
27410     0x11/imm32/alloc-id:fake:payload
27411     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
27412     0x11/imm32/alloc-id:fake
27413     _string-and/imm32/name
27414     0x11/imm32/alloc-id:fake
27415     Single-int-var-in-mem/imm32/inouts
27416     0x11/imm32/alloc-id:fake
27417     Single-int-var-in-some-register/imm32/outputs
27418     0x11/imm32/alloc-id:fake
27419     _string_23_and/imm32/subx-name
27420     1/imm32/rm32-is-first-inout
27421     3/imm32/r32-is-first-output
27422     0/imm32/no-imm32
27423     0/imm32/no-imm8
27424     0/imm32/no-disp32
27425     0/imm32/no-xm32
27426     0/imm32/no-x32
27427     0x11/imm32/alloc-id:fake
27428     _Primitive-and-lit-with-reg/imm32/next
27429 _Primitive-and-lit-with-reg:  # (payload primitive)
27430     0x11/imm32/alloc-id:fake:payload
27431     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
27432     0x11/imm32/alloc-id:fake
27433     _string-and/imm32/name
27434     0x11/imm32/alloc-id:fake
27435     Single-lit-var/imm32/inouts
27436     0x11/imm32/alloc-id:fake
27437     Single-int-var-in-some-register/imm32/outputs
27438     0x11/imm32/alloc-id:fake
27439     _string_81_subop_and/imm32/subx-name
27440     3/imm32/rm32-is-first-output
27441     0/imm32/no-r32
27442     1/imm32/imm32-is-first-inout
27443     0/imm32/no-imm8
27444     0/imm32/no-disp32
27445     0/imm32/no-xm32
27446     0/imm32/no-x32
27447     0x11/imm32/alloc-id:fake
27448     _Primitive-and-lit-with-mem/imm32/next
27449 _Primitive-and-lit-with-mem:  # (payload primitive)
27450     0x11/imm32/alloc-id:fake:payload
27451     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
27452     0x11/imm32/alloc-id:fake
27453     _string-and-with/imm32/name
27454     0x11/imm32/alloc-id:fake
27455     Int-var-and-literal/imm32/inouts
27456     0/imm32/no-outputs
27457     0/imm32/no-outputs
27458     0x11/imm32/alloc-id:fake
27459     _string_81_subop_and/imm32/subx-name
27460     1/imm32/rm32-is-first-inout
27461     0/imm32/no-r32
27462     2/imm32/imm32-is-second-inout
27463     0/imm32/no-imm8
27464     0/imm32/no-disp32
27465     0/imm32/no-xm32
27466     0/imm32/no-x32
27467     0x11/imm32/alloc-id:fake
27468     _Primitive-or-with-eax/imm32/next
27469 # - or
27470 _Primitive-or-with-eax:  # (payload primitive)
27471     0x11/imm32/alloc-id:fake:payload
27472     # var/eax <- or lit => 0d/or-with-eax lit/imm32
27473     0x11/imm32/alloc-id:fake
27474     _string-or/imm32/name
27475     0x11/imm32/alloc-id:fake
27476     Single-lit-var/imm32/inouts
27477     0x11/imm32/alloc-id:fake
27478     Single-int-var-in-eax/imm32/outputs
27479     0x11/imm32/alloc-id:fake
27480     _string_0d_or_with_eax/imm32/subx-name
27481     0/imm32/no-rm32
27482     0/imm32/no-r32
27483     1/imm32/imm32-is-first-inout
27484     0/imm32/no-imm8
27485     0/imm32/no-disp32
27486     0/imm32/no-xm32
27487     0/imm32/no-x32
27488     0x11/imm32/alloc-id:fake
27489     _Primitive-or-reg-with-reg/imm32/next
27490 _Primitive-or-reg-with-reg:  # (payload primitive)
27491     0x11/imm32/alloc-id:fake:payload
27492     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
27493     0x11/imm32/alloc-id:fake
27494     _string-or/imm32/name
27495     0x11/imm32/alloc-id:fake
27496     Single-int-var-in-some-register/imm32/inouts
27497     0x11/imm32/alloc-id:fake
27498     Single-int-var-in-some-register/imm32/outputs
27499     0x11/imm32/alloc-id:fake
27500     _string_09_or_with/imm32/subx-name
27501     3/imm32/rm32-is-first-output
27502     1/imm32/r32-is-first-inout
27503     0/imm32/no-imm32
27504     0/imm32/no-imm8
27505     0/imm32/no-disp32
27506     0/imm32/no-xm32
27507     0/imm32/no-x32
27508     0x11/imm32/alloc-id:fake
27509     _Primitive-or-reg-with-mem/imm32/next
27510 _Primitive-or-reg-with-mem:  # (payload primitive)
27511     0x11/imm32/alloc-id:fake:payload
27512     # or-with var1 var2/reg => 09/or-with var1 var2/r32
27513     0x11/imm32/alloc-id:fake
27514     _string-or-with/imm32/name
27515     0x11/imm32/alloc-id:fake
27516     Two-args-int-stack-int-reg/imm32/inouts
27517     0/imm32/no-outputs
27518     0/imm32/no-outputs
27519     0x11/imm32/alloc-id:fake
27520     _string_09_or_with/imm32/subx-name
27521     1/imm32/rm32-is-first-inout
27522     2/imm32/r32-is-second-inout
27523     0/imm32/no-imm32
27524     0/imm32/no-imm8
27525     0/imm32/no-disp32
27526     0/imm32/no-xm32
27527     0/imm32/no-x32
27528     0x11/imm32/alloc-id:fake
27529     _Primitive-or-mem-with-reg/imm32/next
27530 _Primitive-or-mem-with-reg:  # (payload primitive)
27531     0x11/imm32/alloc-id:fake:payload
27532     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
27533     0x11/imm32/alloc-id:fake
27534     _string-or/imm32/name
27535     0x11/imm32/alloc-id:fake
27536     Single-int-var-in-mem/imm32/inouts
27537     0x11/imm32/alloc-id:fake
27538     Single-int-var-in-some-register/imm32/outputs
27539     0x11/imm32/alloc-id:fake
27540     _string_0b_or/imm32/subx-name
27541     1/imm32/rm32-is-first-inout
27542     3/imm32/r32-is-first-output
27543     0/imm32/no-imm32
27544     0/imm32/no-imm8
27545     0/imm32/no-disp32
27546     0/imm32/no-xm32
27547     0/imm32/no-x32
27548     0x11/imm32/alloc-id:fake
27549     _Primitive-or-lit-with-reg/imm32/next
27550 _Primitive-or-lit-with-reg:  # (payload primitive)
27551     0x11/imm32/alloc-id:fake:payload
27552     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
27553     0x11/imm32/alloc-id:fake
27554     _string-or/imm32/name
27555     0x11/imm32/alloc-id:fake
27556     Single-lit-var/imm32/inouts
27557     0x11/imm32/alloc-id:fake
27558     Single-int-var-in-some-register/imm32/outputs
27559     0x11/imm32/alloc-id:fake
27560     _string_81_subop_or/imm32/subx-name
27561     3/imm32/rm32-is-first-output
27562     0/imm32/no-r32
27563     1/imm32/imm32-is-first-inout
27564     0/imm32/no-imm8
27565     0/imm32/no-disp32
27566     0/imm32/no-xm32
27567     0/imm32/no-x32
27568     0x11/imm32/alloc-id:fake
27569     _Primitive-or-lit-with-mem/imm32/next
27570 _Primitive-or-lit-with-mem:  # (payload primitive)
27571     0x11/imm32/alloc-id:fake:payload
27572     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
27573     0x11/imm32/alloc-id:fake
27574     _string-or-with/imm32/name
27575     0x11/imm32/alloc-id:fake
27576     Int-var-and-literal/imm32/inouts
27577     0/imm32/no-outputs
27578     0/imm32/no-outputs
27579     0x11/imm32/alloc-id:fake
27580     _string_81_subop_or/imm32/subx-name
27581     1/imm32/rm32-is-first-inout
27582     0/imm32/no-r32
27583     2/imm32/imm32-is-second-inout
27584     0/imm32/no-imm8
27585     0/imm32/no-disp32
27586     0/imm32/no-xm32
27587     0/imm32/no-x32
27588     0x11/imm32/alloc-id:fake
27589     _Primitive-xor-with-eax/imm32/next
27590 # - xor
27591 _Primitive-xor-with-eax:  # (payload primitive)
27592     0x11/imm32/alloc-id:fake:payload
27593     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
27594     0x11/imm32/alloc-id:fake
27595     _string-xor/imm32/name
27596     0x11/imm32/alloc-id:fake
27597     Single-lit-var/imm32/inouts
27598     0x11/imm32/alloc-id:fake
27599     Single-int-var-in-eax/imm32/outputs
27600     0x11/imm32/alloc-id:fake
27601     _string_35_xor_with_eax/imm32/subx-name
27602     0/imm32/no-rm32
27603     0/imm32/no-r32
27604     1/imm32/imm32-is-first-inout
27605     0/imm32/no-imm8
27606     0/imm32/no-disp32
27607     0/imm32/no-xm32
27608     0/imm32/no-x32
27609     0x11/imm32/alloc-id:fake
27610     _Primitive-xor-reg-with-reg/imm32/next
27611 _Primitive-xor-reg-with-reg:  # (payload primitive)
27612     0x11/imm32/alloc-id:fake:payload
27613     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
27614     0x11/imm32/alloc-id:fake
27615     _string-xor/imm32/name
27616     0x11/imm32/alloc-id:fake
27617     Single-int-var-in-some-register/imm32/inouts
27618     0x11/imm32/alloc-id:fake
27619     Single-int-var-in-some-register/imm32/outputs
27620     0x11/imm32/alloc-id:fake
27621     _string_31_xor_with/imm32/subx-name
27622     3/imm32/rm32-is-first-output
27623     1/imm32/r32-is-first-inout
27624     0/imm32/no-imm32
27625     0/imm32/no-imm8
27626     0/imm32/no-disp32
27627     0/imm32/no-xm32
27628     0/imm32/no-x32
27629     0x11/imm32/alloc-id:fake
27630     _Primitive-xor-reg-with-mem/imm32/next
27631 _Primitive-xor-reg-with-mem:  # (payload primitive)
27632     0x11/imm32/alloc-id:fake:payload
27633     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
27634     0x11/imm32/alloc-id:fake
27635     _string-xor-with/imm32/name
27636     0x11/imm32/alloc-id:fake
27637     Two-args-int-stack-int-reg/imm32/inouts
27638     0/imm32/no-outputs
27639     0/imm32/no-outputs
27640     0x11/imm32/alloc-id:fake
27641     _string_31_xor_with/imm32/subx-name
27642     1/imm32/rm32-is-first-inout
27643     2/imm32/r32-is-second-inout
27644     0/imm32/no-imm32
27645     0/imm32/no-imm8
27646     0/imm32/no-disp32
27647     0/imm32/no-xm32
27648     0/imm32/no-x32
27649     0x11/imm32/alloc-id:fake
27650     _Primitive-xor-mem-with-reg/imm32/next
27651 _Primitive-xor-mem-with-reg:  # (payload primitive)
27652     0x11/imm32/alloc-id:fake:payload
27653     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
27654     0x11/imm32/alloc-id:fake
27655     _string-xor/imm32/name
27656     0x11/imm32/alloc-id:fake
27657     Single-int-var-in-mem/imm32/inouts
27658     0x11/imm32/alloc-id:fake
27659     Single-int-var-in-some-register/imm32/outputs
27660     0x11/imm32/alloc-id:fake
27661     _string_33_xor/imm32/subx-name
27662     1/imm32/rm32-is-first-inout
27663     3/imm32/r32-is-first-output
27664     0/imm32/no-imm32
27665     0/imm32/no-imm8
27666     0/imm32/no-disp32
27667     0/imm32/no-xm32
27668     0/imm32/no-x32
27669     0x11/imm32/alloc-id:fake
27670     _Primitive-xor-lit-with-reg/imm32/next
27671 _Primitive-xor-lit-with-reg:  # (payload primitive)
27672     0x11/imm32/alloc-id:fake:payload
27673     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
27674     0x11/imm32/alloc-id:fake
27675     _string-xor/imm32/name
27676     0x11/imm32/alloc-id:fake
27677     Single-lit-var/imm32/inouts
27678     0x11/imm32/alloc-id:fake
27679     Single-int-var-in-some-register/imm32/outputs
27680     0x11/imm32/alloc-id:fake
27681     _string_81_subop_xor/imm32/subx-name
27682     3/imm32/rm32-is-first-output
27683     0/imm32/no-r32
27684     1/imm32/imm32-is-first-inout
27685     0/imm32/no-imm8
27686     0/imm32/no-disp32
27687     0/imm32/no-xm32
27688     0/imm32/no-x32
27689     0x11/imm32/alloc-id:fake
27690     _Primitive-xor-lit-with-mem/imm32/next
27691 _Primitive-xor-lit-with-mem:  # (payload primitive)
27692     0x11/imm32/alloc-id:fake:payload
27693     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
27694     0x11/imm32/alloc-id:fake
27695     _string-xor-with/imm32/name
27696     0x11/imm32/alloc-id:fake
27697     Int-var-and-literal/imm32/inouts
27698     0/imm32/no-outputs
27699     0/imm32/no-outputs
27700     0x11/imm32/alloc-id:fake
27701     _string_81_subop_xor/imm32/subx-name
27702     1/imm32/rm32-is-first-inout
27703     0/imm32/no-r32
27704     2/imm32/imm32-is-second-inout
27705     0/imm32/no-imm8
27706     0/imm32/no-disp32
27707     0/imm32/no-xm32
27708     0/imm32/no-x32
27709     0x11/imm32/alloc-id:fake
27710     _Primitive-shift-reg-left-by-lit/imm32/next
27711 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
27712     0x11/imm32/alloc-id:fake:payload
27713     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
27714     0x11/imm32/alloc-id:fake
27715     _string-shift-left/imm32/name
27716     0x11/imm32/alloc-id:fake
27717     Single-lit-var/imm32/inouts
27718     0x11/imm32/alloc-id:fake
27719     Single-int-var-in-some-register/imm32/outputs
27720     0x11/imm32/alloc-id:fake
27721     _string_c1_subop_shift_left/imm32/subx-name
27722     3/imm32/rm32-is-first-output
27723     0/imm32/no-r32
27724     0/imm32/no-imm32
27725     1/imm32/imm8-is-first-inout
27726     0/imm32/no-disp32
27727     0/imm32/no-xm32
27728     0/imm32/no-x32
27729     0x11/imm32/alloc-id:fake
27730     _Primitive-shift-reg-right-by-lit/imm32/next
27731 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
27732     0x11/imm32/alloc-id:fake:payload
27733     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
27734     0x11/imm32/alloc-id:fake
27735     _string-shift-right/imm32/name
27736     0x11/imm32/alloc-id:fake
27737     Single-lit-var/imm32/inouts
27738     0x11/imm32/alloc-id:fake
27739     Single-int-var-in-some-register/imm32/outputs
27740     0x11/imm32/alloc-id:fake
27741     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
27742     3/imm32/rm32-is-first-output
27743     0/imm32/no-r32
27744     0/imm32/no-imm32
27745     1/imm32/imm8-is-first-inout
27746     0/imm32/no-disp32
27747     0/imm32/no-xm32
27748     0/imm32/no-x32
27749     0x11/imm32/alloc-id:fake
27750     _Primitive-shift-reg-right-signed-by-lit/imm32/next
27751 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
27752     0x11/imm32/alloc-id:fake:payload
27753     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
27754     0x11/imm32/alloc-id:fake
27755     _string-shift-right-signed/imm32/name
27756     0x11/imm32/alloc-id:fake
27757     Single-lit-var/imm32/inouts
27758     0x11/imm32/alloc-id:fake
27759     Single-int-var-in-some-register/imm32/outputs
27760     0x11/imm32/alloc-id:fake
27761     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
27762     3/imm32/rm32-is-first-output
27763     0/imm32/no-r32
27764     0/imm32/no-imm32
27765     1/imm32/imm8-is-first-inout
27766     0/imm32/no-disp32
27767     0/imm32/no-xm32
27768     0/imm32/no-x32
27769     0x11/imm32/alloc-id:fake
27770     _Primitive-shift-mem-left-by-lit/imm32/next
27771 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
27772     0x11/imm32/alloc-id:fake:payload
27773     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
27774     0x11/imm32/alloc-id:fake
27775     _string-shift-left/imm32/name
27776     0x11/imm32/alloc-id:fake
27777     Int-var-and-literal/imm32/inouts
27778     0/imm32/no-outputs
27779     0/imm32/no-outputs
27780     0x11/imm32/alloc-id:fake
27781     _string_c1_subop_shift_left/imm32/subx-name
27782     1/imm32/rm32-is-first-inout
27783     0/imm32/no-r32
27784     0/imm32/no-imm32
27785     2/imm32/imm8-is-second-inout
27786     0/imm32/no-disp32
27787     0/imm32/no-xm32
27788     0/imm32/no-x32
27789     0x11/imm32/alloc-id:fake
27790     _Primitive-shift-mem-right-by-lit/imm32/next
27791 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
27792     0x11/imm32/alloc-id:fake:payload
27793     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
27794     0x11/imm32/alloc-id:fake
27795     _string-shift-right/imm32/name
27796     0x11/imm32/alloc-id:fake
27797     Int-var-and-literal/imm32/inouts
27798     0/imm32/no-outputs
27799     0/imm32/no-outputs
27800     0x11/imm32/alloc-id:fake
27801     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
27802     1/imm32/rm32-is-first-inout
27803     0/imm32/no-r32
27804     0/imm32/no-imm32
27805     2/imm32/imm8-is-second-inout
27806     0/imm32/no-disp32
27807     0/imm32/no-xm32
27808     0/imm32/no-x32
27809     0x11/imm32/alloc-id:fake
27810     _Primitive-shift-mem-right-signed-by-lit/imm32/next
27811 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
27812     0x11/imm32/alloc-id:fake:payload
27813     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
27814     0x11/imm32/alloc-id:fake
27815     _string-shift-right-signed/imm32/name
27816     0x11/imm32/alloc-id:fake
27817     Int-var-and-literal/imm32/inouts
27818     0/imm32/no-outputs
27819     0/imm32/no-outputs
27820     0x11/imm32/alloc-id:fake
27821     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
27822     1/imm32/rm32-is-first-inout
27823     0/imm32/no-r32
27824     0/imm32/no-imm32
27825     2/imm32/imm8-is-second-inout
27826     0/imm32/no-disp32
27827     0/imm32/no-xm32
27828     0/imm32/no-x32
27829     0x11/imm32/alloc-id:fake
27830     _Primitive-copy-to-eax/imm32/next
27831 # - copy
27832 _Primitive-copy-to-eax:  # (payload primitive)
27833     0x11/imm32/alloc-id:fake:payload
27834     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
27835     0x11/imm32/alloc-id:fake
27836     _string-copy/imm32/name
27837     0x11/imm32/alloc-id:fake
27838     Single-lit-var/imm32/inouts
27839     0x11/imm32/alloc-id:fake
27840     Single-int-var-in-eax/imm32/outputs
27841     0x11/imm32/alloc-id:fake
27842     _string_b8_copy_to_eax/imm32/subx-name
27843     0/imm32/no-rm32
27844     0/imm32/no-r32
27845     1/imm32/imm32-is-first-inout
27846     0/imm32/no-imm8
27847     0/imm32/no-disp32
27848     0/imm32/no-xm32
27849     0/imm32/no-x32
27850     0x11/imm32/alloc-id:fake
27851     _Primitive-copy-to-ecx/imm32/next
27852 _Primitive-copy-to-ecx:  # (payload primitive)
27853     0x11/imm32/alloc-id:fake:payload
27854     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
27855     0x11/imm32/alloc-id:fake
27856     _string-copy/imm32/name
27857     0x11/imm32/alloc-id:fake
27858     Single-lit-var/imm32/inouts
27859     0x11/imm32/alloc-id:fake
27860     Single-int-var-in-ecx/imm32/outputs
27861     0x11/imm32/alloc-id:fake
27862     _string_b9_copy_to_ecx/imm32/subx-name
27863     0/imm32/no-rm32
27864     0/imm32/no-r32
27865     1/imm32/imm32-is-first-inout
27866     0/imm32/no-imm8
27867     0/imm32/no-disp32
27868     0/imm32/no-xm32
27869     0/imm32/no-x32
27870     0x11/imm32/alloc-id:fake
27871     _Primitive-copy-to-edx/imm32/next
27872 _Primitive-copy-to-edx:  # (payload primitive)
27873     0x11/imm32/alloc-id:fake:payload
27874     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
27875     0x11/imm32/alloc-id:fake
27876     _string-copy/imm32/name
27877     0x11/imm32/alloc-id:fake
27878     Single-lit-var/imm32/inouts
27879     0x11/imm32/alloc-id:fake
27880     Single-int-var-in-edx/imm32/outputs
27881     0x11/imm32/alloc-id:fake
27882     _string_ba_copy_to_edx/imm32/subx-name
27883     0/imm32/no-rm32
27884     0/imm32/no-r32
27885     1/imm32/imm32-is-first-inout
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-copy-to-ebx/imm32/next
27892 _Primitive-copy-to-ebx:  # (payload primitive)
27893     0x11/imm32/alloc-id:fake:payload
27894     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
27895     0x11/imm32/alloc-id:fake
27896     _string-copy/imm32/name
27897     0x11/imm32/alloc-id:fake
27898     Single-lit-var/imm32/inouts
27899     0x11/imm32/alloc-id:fake
27900     Single-int-var-in-ebx/imm32/outputs
27901     0x11/imm32/alloc-id:fake
27902     _string_bb_copy_to_ebx/imm32/subx-name
27903     0/imm32/no-rm32
27904     0/imm32/no-r32
27905     1/imm32/imm32-is-first-inout
27906     0/imm32/no-imm8
27907     0/imm32/no-disp32
27908     0/imm32/no-xm32
27909     0/imm32/no-x32
27910     0x11/imm32/alloc-id:fake
27911     _Primitive-copy-to-esi/imm32/next
27912 _Primitive-copy-to-esi:  # (payload primitive)
27913     0x11/imm32/alloc-id:fake:payload
27914     # var/esi <- copy lit => be/copy-to-esi lit/imm32
27915     0x11/imm32/alloc-id:fake
27916     _string-copy/imm32/name
27917     0x11/imm32/alloc-id:fake
27918     Single-lit-var/imm32/inouts
27919     0x11/imm32/alloc-id:fake
27920     Single-int-var-in-esi/imm32/outputs
27921     0x11/imm32/alloc-id:fake
27922     _string_be_copy_to_esi/imm32/subx-name
27923     0/imm32/no-rm32
27924     0/imm32/no-r32
27925     1/imm32/imm32-is-first-inout
27926     0/imm32/no-imm8
27927     0/imm32/no-disp32
27928     0/imm32/no-xm32
27929     0/imm32/no-x32
27930     0x11/imm32/alloc-id:fake
27931     _Primitive-copy-to-edi/imm32/next
27932 _Primitive-copy-to-edi:  # (payload primitive)
27933     0x11/imm32/alloc-id:fake:payload
27934     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
27935     0x11/imm32/alloc-id:fake
27936     _string-copy/imm32/name
27937     0x11/imm32/alloc-id:fake
27938     Single-lit-var/imm32/inouts
27939     0x11/imm32/alloc-id:fake
27940     Single-int-var-in-edi/imm32/outputs
27941     0x11/imm32/alloc-id:fake
27942     _string_bf_copy_to_edi/imm32/subx-name
27943     0/imm32/no-rm32
27944     0/imm32/no-r32
27945     1/imm32/imm32-is-first-inout
27946     0/imm32/no-imm8
27947     0/imm32/no-disp32
27948     0/imm32/no-xm32
27949     0/imm32/no-x32
27950     0x11/imm32/alloc-id:fake
27951     _Primitive-copy-reg-to-reg/imm32/next
27952 _Primitive-copy-reg-to-reg:  # (payload primitive)
27953     0x11/imm32/alloc-id:fake:payload
27954     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
27955     0x11/imm32/alloc-id:fake
27956     _string-copy/imm32/name
27957     0x11/imm32/alloc-id:fake
27958     Single-int-var-in-some-register/imm32/inouts
27959     0x11/imm32/alloc-id:fake
27960     Single-int-var-in-some-register/imm32/outputs
27961     0x11/imm32/alloc-id:fake
27962     _string_89_<-/imm32/subx-name
27963     3/imm32/rm32-is-first-output
27964     1/imm32/r32-is-first-inout
27965     0/imm32/no-imm32
27966     0/imm32/no-imm8
27967     0/imm32/no-disp32
27968     0/imm32/no-xm32
27969     0/imm32/no-x32
27970     0x11/imm32/alloc-id:fake
27971     _Primitive-copy-reg-to-mem/imm32/next
27972 _Primitive-copy-reg-to-mem:  # (payload primitive)
27973     0x11/imm32/alloc-id:fake:payload
27974     # copy-to var1 var2/reg => 89/<- var1 var2/r32
27975     0x11/imm32/alloc-id:fake
27976     _string-copy-to/imm32/name
27977     0x11/imm32/alloc-id:fake
27978     Two-args-int-stack-int-reg/imm32/inouts
27979     0/imm32/no-outputs
27980     0/imm32/no-outputs
27981     0x11/imm32/alloc-id:fake
27982     _string_89_<-/imm32/subx-name
27983     1/imm32/rm32-is-first-inout
27984     2/imm32/r32-is-second-inout
27985     0/imm32/no-imm32
27986     0/imm32/no-imm8
27987     0/imm32/no-disp32
27988     0/imm32/no-xm32
27989     0/imm32/no-x32
27990     0x11/imm32/alloc-id:fake
27991     _Primitive-copy-mem-to-reg/imm32/next
27992 _Primitive-copy-mem-to-reg:  # (payload primitive)
27993     0x11/imm32/alloc-id:fake:payload
27994     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
27995     0x11/imm32/alloc-id:fake
27996     _string-copy/imm32/name
27997     0x11/imm32/alloc-id:fake
27998     Single-int-var-in-mem/imm32/inouts
27999     0x11/imm32/alloc-id:fake
28000     Single-int-var-in-some-register/imm32/outputs
28001     0x11/imm32/alloc-id:fake
28002     _string_8b_->/imm32/subx-name
28003     1/imm32/rm32-is-first-inout
28004     3/imm32/r32-is-first-output
28005     0/imm32/no-imm32
28006     0/imm32/no-imm8
28007     0/imm32/no-disp32
28008     0/imm32/no-xm32
28009     0/imm32/no-x32
28010     0x11/imm32/alloc-id:fake
28011     _Primitive-copy-lit-to-reg/imm32/next
28012 _Primitive-copy-lit-to-reg:  # (payload primitive)
28013     0x11/imm32/alloc-id:fake:payload
28014     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
28015     0x11/imm32/alloc-id:fake
28016     _string-copy/imm32/name
28017     0x11/imm32/alloc-id:fake
28018     Single-lit-var/imm32/inouts
28019     0x11/imm32/alloc-id:fake
28020     Single-int-var-in-some-register/imm32/outputs
28021     0x11/imm32/alloc-id:fake
28022     _string_c7_subop_copy/imm32/subx-name
28023     3/imm32/rm32-is-first-output
28024     0/imm32/no-r32
28025     1/imm32/imm32-is-first-inout
28026     0/imm32/no-imm8
28027     0/imm32/no-disp32
28028     0/imm32/no-xm32
28029     0/imm32/no-x32
28030     0x11/imm32/alloc-id:fake
28031     _Primitive-copy-lit-to-mem/imm32/next
28032 _Primitive-copy-lit-to-mem:  # (payload primitive)
28033     0x11/imm32/alloc-id:fake:payload
28034     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
28035     0x11/imm32/alloc-id:fake
28036     _string-copy-to/imm32/name
28037     0x11/imm32/alloc-id:fake
28038     Int-var-and-literal/imm32/inouts
28039     0/imm32/no-outputs
28040     0/imm32/no-outputs
28041     0x11/imm32/alloc-id:fake
28042     _string_c7_subop_copy/imm32/subx-name
28043     1/imm32/rm32-is-first-inout
28044     0/imm32/no-r32
28045     2/imm32/imm32-is-second-inout
28046     0/imm32/no-imm8
28047     0/imm32/no-disp32
28048     0/imm32/no-xm32
28049     0/imm32/no-x32
28050     0x11/imm32/alloc-id:fake
28051     _Primitive-copy-byte-from-reg/imm32/next
28052 # - copy byte
28053 _Primitive-copy-byte-from-reg:
28054     0x11/imm32/alloc-id:fake:payload
28055     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
28056     0x11/imm32/alloc-id:fake
28057     _string-copy-byte/imm32/name
28058     0x11/imm32/alloc-id:fake
28059     Single-byte-var-in-some-register/imm32/inouts
28060     0x11/imm32/alloc-id:fake
28061     Single-byte-var-in-some-register/imm32/outputs
28062     0x11/imm32/alloc-id:fake
28063     _string_8a_copy_byte/imm32/subx-name
28064     1/imm32/rm32-is-first-inout
28065     3/imm32/r32-is-first-output
28066     0/imm32/no-imm32
28067     0/imm32/no-imm8
28068     0/imm32/no-disp32
28069     0/imm32/no-xm32
28070     0/imm32/no-x32
28071     0x11/imm32/alloc-id:fake
28072     _Primitive-copy-byte-from-mem/imm32/next
28073 _Primitive-copy-byte-from-mem:
28074     0x11/imm32/alloc-id:fake:payload
28075     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
28076     0x11/imm32/alloc-id:fake
28077     _string-copy-byte/imm32/name
28078     0x11/imm32/alloc-id:fake
28079     Single-byte-var-in-mem/imm32/inouts
28080     0x11/imm32/alloc-id:fake
28081     Single-byte-var-in-some-register/imm32/outputs
28082     0x11/imm32/alloc-id:fake
28083     _string_8a_copy_byte/imm32/subx-name
28084     1/imm32/rm32-is-first-inout
28085     3/imm32/r32-is-first-output
28086     0/imm32/no-imm32
28087     0/imm32/no-imm8
28088     0/imm32/no-disp32
28089     0/imm32/no-xm32
28090     0/imm32/no-x32
28091     0x11/imm32/alloc-id:fake
28092     _Primitive-copy-byte-to-mem/imm32/next
28093 _Primitive-copy-byte-to-mem:
28094     0x11/imm32/alloc-id:fake:payload
28095     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
28096     0x11/imm32/alloc-id:fake
28097     _string-copy-byte-to/imm32/name
28098     0x11/imm32/alloc-id:fake
28099     Two-args-byte-stack-byte-reg/imm32/inouts
28100     0/imm32/no-outputs
28101     0/imm32/no-outputs
28102     0x11/imm32/alloc-id:fake
28103     _string_88_copy_byte/imm32/subx-name
28104     1/imm32/rm32-is-first-inout
28105     2/imm32/r32-is-second-inout
28106     0/imm32/no-imm32
28107     0/imm32/no-imm8
28108     0/imm32/no-disp32
28109     0/imm32/no-xm32
28110     0/imm32/no-x32
28111     0x11/imm32/alloc-id:fake
28112     _Primitive-address/imm32/next
28113 # - address
28114 _Primitive-address:  # (payload primitive)
28115     0x11/imm32/alloc-id:fake:payload
28116     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
28117     0x11/imm32/alloc-id:fake
28118     _string-address/imm32/name
28119     0x11/imm32/alloc-id:fake
28120     Single-int-var-in-mem/imm32/inouts
28121     0x11/imm32/alloc-id:fake
28122     Single-addr-var-in-some-register/imm32/outputs
28123     0x11/imm32/alloc-id:fake
28124     _string_8d_copy_address/imm32/subx-name
28125     1/imm32/rm32-is-first-inout
28126     3/imm32/r32-is-first-output
28127     0/imm32/no-imm32
28128     0/imm32/no-imm8
28129     0/imm32/no-disp32
28130     0/imm32/no-xm32
28131     0/imm32/no-x32
28132     0x11/imm32/alloc-id:fake
28133     _Primitive-compare-reg-with-reg/imm32/next
28134 # - compare
28135 _Primitive-compare-reg-with-reg:  # (payload primitive)
28136     0x11/imm32/alloc-id:fake:payload
28137     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
28138     0x11/imm32/alloc-id:fake
28139     _string-compare/imm32/name
28140     0x11/imm32/alloc-id:fake
28141     Two-int-args-in-regs/imm32/inouts
28142     0/imm32/no-outputs
28143     0/imm32/no-outputs
28144     0x11/imm32/alloc-id:fake
28145     _string_39_compare->/imm32/subx-name
28146     1/imm32/rm32-is-first-inout
28147     2/imm32/r32-is-second-inout
28148     0/imm32/no-imm32
28149     0/imm32/no-imm8
28150     0/imm32/no-disp32
28151     0/imm32/no-xm32
28152     0/imm32/no-x32
28153     0x11/imm32/alloc-id:fake
28154     _Primitive-compare-mem-with-reg/imm32/next
28155 _Primitive-compare-mem-with-reg:  # (payload primitive)
28156     0x11/imm32/alloc-id:fake:payload
28157     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
28158     0x11/imm32/alloc-id:fake
28159     _string-compare/imm32/name
28160     0x11/imm32/alloc-id:fake
28161     Two-args-int-stack-int-reg/imm32/inouts
28162     0/imm32/no-outputs
28163     0/imm32/no-outputs
28164     0x11/imm32/alloc-id:fake
28165     _string_39_compare->/imm32/subx-name
28166     1/imm32/rm32-is-first-inout
28167     2/imm32/r32-is-second-inout
28168     0/imm32/no-imm32
28169     0/imm32/no-imm8
28170     0/imm32/no-disp32
28171     0/imm32/no-xm32
28172     0/imm32/no-x32
28173     0x11/imm32/alloc-id:fake
28174     _Primitive-compare-reg-with-mem/imm32/next
28175 _Primitive-compare-reg-with-mem:  # (payload primitive)
28176     0x11/imm32/alloc-id:fake:payload
28177     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
28178     0x11/imm32/alloc-id:fake
28179     _string-compare/imm32/name
28180     0x11/imm32/alloc-id:fake
28181     Two-args-int-reg-int-stack/imm32/inouts
28182     0/imm32/no-outputs
28183     0/imm32/no-outputs
28184     0x11/imm32/alloc-id:fake
28185     _string_3b_compare<-/imm32/subx-name
28186     2/imm32/rm32-is-second-inout
28187     1/imm32/r32-is-first-inout
28188     0/imm32/no-imm32
28189     0/imm32/no-imm8
28190     0/imm32/no-disp32
28191     0/imm32/no-xm32
28192     0/imm32/no-x32
28193     0x11/imm32/alloc-id:fake
28194     _Primitive-compare-eax-with-literal/imm32/next
28195 _Primitive-compare-eax-with-literal:  # (payload primitive)
28196     0x11/imm32/alloc-id:fake:payload
28197     # compare var1/eax n => 3d/compare-eax-with n/imm32
28198     0x11/imm32/alloc-id:fake
28199     _string-compare/imm32/name
28200     0x11/imm32/alloc-id:fake
28201     Two-args-int-eax-int-literal/imm32/inouts
28202     0/imm32/no-outputs
28203     0/imm32/no-outputs
28204     0x11/imm32/alloc-id:fake
28205     _string_3d_compare_eax_with/imm32/subx-name
28206     0/imm32/no-rm32
28207     0/imm32/no-r32
28208     2/imm32/imm32-is-second-inout
28209     0/imm32/no-imm8
28210     0/imm32/no-disp32
28211     0/imm32/no-xm32
28212     0/imm32/no-x32
28213     0x11/imm32/alloc-id:fake
28214     _Primitive-compare-reg-with-literal/imm32/next
28215 _Primitive-compare-reg-with-literal:  # (payload primitive)
28216     0x11/imm32/alloc-id:fake:payload
28217     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
28218     0x11/imm32/alloc-id:fake
28219     _string-compare/imm32/name
28220     0x11/imm32/alloc-id:fake
28221     Int-var-in-register-and-literal/imm32/inouts
28222     0/imm32/no-outputs
28223     0/imm32/no-outputs
28224     0x11/imm32/alloc-id:fake
28225     _string_81_subop_compare/imm32/subx-name
28226     1/imm32/rm32-is-first-inout
28227     0/imm32/no-r32
28228     2/imm32/imm32-is-second-inout
28229     0/imm32/no-imm8
28230     0/imm32/no-disp32
28231     0/imm32/no-xm32
28232     0/imm32/no-x32
28233     0x11/imm32/alloc-id:fake
28234     _Primitive-compare-mem-with-literal/imm32/next
28235 _Primitive-compare-mem-with-literal:  # (payload primitive)
28236     0x11/imm32/alloc-id:fake:payload
28237     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
28238     0x11/imm32/alloc-id:fake
28239     _string-compare/imm32/name
28240     0x11/imm32/alloc-id:fake
28241     Int-var-and-literal/imm32/inouts
28242     0/imm32/no-outputs
28243     0/imm32/no-outputs
28244     0x11/imm32/alloc-id:fake
28245     _string_81_subop_compare/imm32/subx-name
28246     1/imm32/rm32-is-first-inout
28247     0/imm32/no-r32
28248     2/imm32/imm32-is-second-inout
28249     0/imm32/no-imm8
28250     0/imm32/no-disp32
28251     0/imm32/no-xm32
28252     0/imm32/no-x32
28253     0x11/imm32/alloc-id:fake
28254     _Primitive-negate-reg/imm32/next
28255 # - negate
28256 _Primitive-negate-reg:  # (payload primitive)
28257     0x11/imm32/alloc-id:fake:payload
28258     # var1/reg <- negate => f7 3/subop/negate var1/rm32
28259     0x11/imm32/alloc-id:fake
28260     _string-negate/imm32/name
28261     0/imm32/no-inouts
28262     0/imm32/no-inouts
28263     0x11/imm32/alloc-id:fake
28264     Single-int-var-in-some-register/imm32/outputs
28265     0x11/imm32/alloc-id:fake
28266     _string_f7_subop_negate/imm32/subx-name
28267     3/imm32/rm32-is-first-output
28268     0/imm32/no-r32
28269     0/imm32/no-imm32
28270     0/imm32/no-imm8
28271     0/imm32/no-disp32
28272     0/imm32/no-xm32
28273     0/imm32/no-x32
28274     0x11/imm32/alloc-id:fake
28275     _Primitive-negate-mem/imm32/next
28276 _Primitive-negate-mem:  # (payload primitive)
28277     0x11/imm32/alloc-id:fake:payload
28278     # negate var1 => f7 3/subop/negate var1/rm32
28279     0x11/imm32/alloc-id:fake
28280     _string-negate/imm32/name
28281     0x11/imm32/alloc-id:fake
28282     Single-int-var-in-mem/imm32/inouts
28283     0/imm32/no-outputs
28284     0/imm32/no-outputs
28285     0x11/imm32/alloc-id:fake
28286     _string_f7_subop_negate/imm32/subx-name
28287     1/imm32/rm32-is-first-inout
28288     0/imm32/no-r32
28289     0/imm32/no-imm32
28290     0/imm32/no-imm8
28291     0/imm32/no-disp32
28292     0/imm32/no-xm32
28293     0/imm32/no-x32
28294     0x11/imm32/alloc-id:fake
28295     _Primitive-multiply-reg-by-reg/imm32/next
28296 # - multiply
28297 _Primitive-multiply-reg-by-reg:  # (payload primitive)
28298     0x11/imm32/alloc-id:fake:payload
28299     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
28300     0x11/imm32/alloc-id:fake
28301     _string-multiply/imm32/name
28302     0x11/imm32/alloc-id:fake
28303     Single-int-var-in-some-register/imm32/inouts
28304     0x11/imm32/alloc-id:fake
28305     Single-int-var-in-some-register/imm32/outputs
28306     0x11/imm32/alloc-id:fake
28307     _string_0f_af_multiply/imm32/subx-name
28308     1/imm32/rm32-is-first-inout
28309     3/imm32/r32-is-first-output
28310     0/imm32/no-imm32
28311     0/imm32/no-imm8
28312     0/imm32/no-disp32
28313     0/imm32/no-xm32
28314     0/imm32/no-x32
28315     0x11/imm32/alloc-id:fake
28316     _Primitive-multiply-reg-by-mem/imm32/next
28317 _Primitive-multiply-reg-by-mem:  # (payload primitive)
28318     0x11/imm32/alloc-id:fake:payload
28319     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
28320     0x11/imm32/alloc-id:fake
28321     _string-multiply/imm32/name
28322     0x11/imm32/alloc-id:fake
28323     Single-int-var-in-mem/imm32/inouts
28324     0x11/imm32/alloc-id:fake
28325     Single-int-var-in-some-register/imm32/outputs
28326     0x11/imm32/alloc-id:fake
28327     _string_0f_af_multiply/imm32/subx-name
28328     1/imm32/rm32-is-first-inout
28329     3/imm32/r32-is-first-output
28330     0/imm32/no-imm32
28331     0/imm32/no-imm8
28332     0/imm32/no-disp32
28333     0/imm32/no-xm32
28334     0/imm32/no-x32
28335     0x11/imm32/alloc-id:fake
28336     _Primitive-convert-mem-to-xreg/imm32/next
28337 # - convert int to floating point
28338 _Primitive-convert-mem-to-xreg:  # (payload primitive)
28339     0x11/imm32/alloc-id:fake:payload
28340     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
28341     0x11/imm32/alloc-id:fake
28342     _string-convert/imm32/name
28343     0x11/imm32/alloc-id:fake
28344     Single-int-var-in-mem/imm32/inouts
28345     0x11/imm32/alloc-id:fake
28346     Single-float-var-in-some-register/imm32/outputs
28347     0x11/imm32/alloc-id:fake
28348     _string_f3_0f_2a_convert_to_float/imm32/subx-name
28349     1/imm32/rm32-is-first-inout
28350     0/imm32/no-r32
28351     0/imm32/no-imm32
28352     0/imm32/no-imm8
28353     0/imm32/no-disp32
28354     0/imm32/no-xm32
28355     3/imm32/x32-is-first-output
28356     0x11/imm32/alloc-id:fake
28357     _Primitive-convert-reg-to-xreg/imm32/next
28358 _Primitive-convert-reg-to-xreg:  # (payload primitive)
28359     0x11/imm32/alloc-id:fake:payload
28360     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
28361     0x11/imm32/alloc-id:fake
28362     _string-convert/imm32/name
28363     0x11/imm32/alloc-id:fake
28364     Single-int-var-in-some-register/imm32/inouts
28365     0x11/imm32/alloc-id:fake
28366     Single-float-var-in-some-register/imm32/outputs
28367     0x11/imm32/alloc-id:fake
28368     _string_f3_0f_2a_convert_to_float/imm32/subx-name
28369     1/imm32/rm32-is-first-inout
28370     0/imm32/no-r32
28371     0/imm32/no-imm32
28372     0/imm32/no-imm8
28373     0/imm32/no-disp32
28374     0/imm32/no-xm32
28375     3/imm32/x32-is-first-output
28376     0x11/imm32/alloc-id:fake
28377     _Primitive-convert-xmem-to-reg/imm32/next
28378 # - convert floating point to int
28379 _Primitive-convert-xmem-to-reg:  # (payload primitive)
28380     0x11/imm32/alloc-id:fake:payload
28381     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
28382     0x11/imm32/alloc-id:fake
28383     _string-convert/imm32/name
28384     0x11/imm32/alloc-id:fake
28385     Single-float-var-in-mem/imm32/inouts
28386     0x11/imm32/alloc-id:fake
28387     Single-int-var-in-some-register/imm32/outputs
28388     0x11/imm32/alloc-id:fake
28389     _string_f3_0f_2d_convert_to_int/imm32/subx-name
28390     0/imm32/no-rm32
28391     3/imm32/r32-is-first-output
28392     0/imm32/no-imm32
28393     0/imm32/no-imm8
28394     0/imm32/no-disp32
28395     1/imm32/xm32-is-first-inout
28396     0/imm32/no-x32
28397     0x11/imm32/alloc-id:fake
28398     _Primitive-convert-xreg-to-reg/imm32/next
28399 _Primitive-convert-xreg-to-reg:  # (payload primitive)
28400     0x11/imm32/alloc-id:fake:payload
28401     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
28402     0x11/imm32/alloc-id:fake
28403     _string-convert/imm32/name
28404     0x11/imm32/alloc-id:fake
28405     Single-float-var-in-some-register/imm32/inouts
28406     0x11/imm32/alloc-id:fake
28407     Single-int-var-in-some-register/imm32/outputs
28408     0x11/imm32/alloc-id:fake
28409     _string_f3_0f_2d_convert_to_int/imm32/subx-name
28410     0/imm32/no-rm32
28411     3/imm32/r32-is-first-output
28412     0/imm32/no-imm32
28413     0/imm32/no-imm8
28414     0/imm32/no-disp32
28415     1/imm32/xm32-is-first-inout
28416     0/imm32/no-x32
28417     0x11/imm32/alloc-id:fake
28418     _Primitive-truncate-xmem-to-reg/imm32/next
28419 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
28420     0x11/imm32/alloc-id:fake:payload
28421     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
28422     0x11/imm32/alloc-id:fake
28423     _string-truncate/imm32/name
28424     0x11/imm32/alloc-id:fake
28425     Single-float-var-in-mem/imm32/inouts
28426     0x11/imm32/alloc-id:fake
28427     Single-int-var-in-some-register/imm32/outputs
28428     0x11/imm32/alloc-id:fake
28429     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
28430     0/imm32/no-rm32
28431     3/imm32/r32-is-first-output
28432     0/imm32/no-imm32
28433     0/imm32/no-imm8
28434     0/imm32/no-disp32
28435     1/imm32/xm32-is-first-inout
28436     0/imm32/no-x32
28437     0x11/imm32/alloc-id:fake
28438     _Primitive-truncate-xreg-to-reg/imm32/next
28439 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
28440     0x11/imm32/alloc-id:fake:payload
28441     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
28442     0x11/imm32/alloc-id:fake
28443     _string-truncate/imm32/name
28444     0x11/imm32/alloc-id:fake
28445     Single-float-var-in-some-register/imm32/inouts
28446     0x11/imm32/alloc-id:fake
28447     Single-int-var-in-some-register/imm32/outputs
28448     0x11/imm32/alloc-id:fake
28449     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
28450     0/imm32/no-rm32
28451     3/imm32/r32-is-first-output
28452     0/imm32/no-imm32
28453     0/imm32/no-imm8
28454     0/imm32/no-disp32
28455     1/imm32/xm32-is-first-inout
28456     0/imm32/no-x32
28457     0x11/imm32/alloc-id:fake
28458     _Primitive-reinterpret-xmem-as-reg/imm32/next
28459 # - reinterpret bytes (just for debugging)
28460 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
28461     0x11/imm32/alloc-id:fake:payload
28462     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
28463     0x11/imm32/alloc-id:fake
28464     _string-reinterpret/imm32/name
28465     0x11/imm32/alloc-id:fake
28466     Single-float-var-in-mem/imm32/inouts
28467     0x11/imm32/alloc-id:fake
28468     Single-int-var-in-some-register/imm32/outputs
28469     0x11/imm32/alloc-id:fake
28470     _string_8b_->/imm32/subx-name
28471     0/imm32/no-rm32
28472     3/imm32/r32-is-first-output
28473     0/imm32/no-imm32
28474     0/imm32/no-imm8
28475     0/imm32/no-disp32
28476     1/imm32/xm32-is-first-inout
28477     0/imm32/no-x32
28478     0x11/imm32/alloc-id:fake
28479     _Primitive-reinterpret-mem-as-xreg/imm32/next
28480 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
28481     0x11/imm32/alloc-id:fake:payload
28482     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
28483     0x11/imm32/alloc-id:fake
28484     _string-reinterpret/imm32/name
28485     0x11/imm32/alloc-id:fake
28486     Single-int-var-in-mem/imm32/inouts
28487     0x11/imm32/alloc-id:fake
28488     Single-float-var-in-some-register/imm32/outputs
28489     0x11/imm32/alloc-id:fake
28490     _string_f3_0f_10_copy/imm32/subx-name
28491     1/imm32/rm32-is-first-inout
28492     0/imm32/no-r32
28493     0/imm32/no-imm32
28494     0/imm32/no-imm8
28495     0/imm32/no-disp32
28496     0/imm32/no-xm32
28497     3/imm32/x32-is-first-output
28498     0x11/imm32/alloc-id:fake
28499     _Primitive-copy-xreg-to-xreg/imm32/next
28500 # - floating-point copy
28501 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
28502     0x11/imm32/alloc-id:fake:payload
28503     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
28504     0x11/imm32/alloc-id:fake
28505     _string-copy/imm32/name
28506     0x11/imm32/alloc-id:fake
28507     Single-float-var-in-some-register/imm32/inouts
28508     0x11/imm32/alloc-id:fake
28509     Single-float-var-in-some-register/imm32/outputs
28510     0x11/imm32/alloc-id:fake
28511     _string_f3_0f_11_copy/imm32/subx-name
28512     0/imm32/no-rm32
28513     0/imm32/no-r32
28514     0/imm32/no-imm32
28515     0/imm32/no-imm8
28516     0/imm32/no-disp32
28517     3/imm32/xm32-is-first-output
28518     1/imm32/x32-is-first-inout
28519     0x11/imm32/alloc-id:fake
28520     _Primitive-copy-xreg-to-mem/imm32/next
28521 _Primitive-copy-xreg-to-mem:  # (payload primitive)
28522     0x11/imm32/alloc-id:fake:payload
28523     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
28524     0x11/imm32/alloc-id:fake
28525     _string-copy-to/imm32/name
28526     0x11/imm32/alloc-id:fake
28527     Two-args-float-stack-float-reg/imm32/inouts
28528     0/imm32/no-outputs
28529     0/imm32/no-outputs
28530     0x11/imm32/alloc-id:fake
28531     _string_f3_0f_11_copy/imm32/subx-name
28532     0/imm32/no-rm32
28533     0/imm32/no-r32
28534     0/imm32/no-imm32
28535     0/imm32/no-imm8
28536     0/imm32/no-disp32
28537     1/imm32/xm32-is-first-inout
28538     2/imm32/x32-is-second-inout
28539     0x11/imm32/alloc-id:fake
28540     _Primitive-copy-mem-to-xreg/imm32/next
28541 _Primitive-copy-mem-to-xreg:  # (payload primitive)
28542     0x11/imm32/alloc-id:fake:payload
28543     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
28544     0x11/imm32/alloc-id:fake
28545     _string-copy/imm32/name
28546     0x11/imm32/alloc-id:fake
28547     Single-float-var-in-mem/imm32/inouts
28548     0x11/imm32/alloc-id:fake
28549     Single-float-var-in-some-register/imm32/outputs
28550     0x11/imm32/alloc-id:fake
28551     _string_f3_0f_10_copy/imm32/subx-name
28552     0/imm32/no-rm32
28553     0/imm32/no-r32
28554     0/imm32/no-imm32
28555     0/imm32/no-imm8
28556     0/imm32/no-disp32
28557     1/imm32/xm32-is-first-inout
28558     3/imm32/x32-is-first-output
28559     0x11/imm32/alloc-id:fake
28560     _Primitive-address-of-xmem/imm32/next
28561 # - floating-point-address
28562 _Primitive-address-of-xmem:  # (payload primitive)
28563     0x11/imm32/alloc-id:fake:payload
28564     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
28565     0x11/imm32/alloc-id:fake
28566     _string-address/imm32/name
28567     0x11/imm32/alloc-id:fake
28568     Single-float-var-in-mem/imm32/inouts
28569     0x11/imm32/alloc-id:fake
28570     Single-addr-var-in-some-register/imm32/outputs
28571     0x11/imm32/alloc-id:fake
28572     _string_8d_copy_address/imm32/subx-name
28573     1/imm32/rm32-is-first-inout
28574     3/imm32/r32-is-first-output
28575     0/imm32/no-imm32
28576     0/imm32/no-imm8
28577     0/imm32/no-disp32
28578     0/imm32/no-xm32
28579     0/imm32/no-x32
28580     0x11/imm32/alloc-id:fake
28581     _Primitive-add-xreg-to-xreg/imm32/next
28582 # - floating-point add
28583 _Primitive-add-xreg-to-xreg:  # (payload primitive)
28584     0x11/imm32/alloc-id:fake:payload
28585     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
28586     0x11/imm32/alloc-id:fake
28587     _string-add/imm32/name
28588     0x11/imm32/alloc-id:fake
28589     Single-float-var-in-some-register/imm32/inouts
28590     0x11/imm32/alloc-id:fake
28591     Single-float-var-in-some-register/imm32/outputs
28592     0x11/imm32/alloc-id:fake
28593     _string_f3_0f_58_add/imm32/subx-name
28594     0/imm32/no-rm32
28595     0/imm32/no-r32
28596     0/imm32/no-imm32
28597     0/imm32/no-imm8
28598     0/imm32/no-disp32
28599     1/imm32/xm32-is-first-inout
28600     3/imm32/x32-is-first-output
28601     0x11/imm32/alloc-id:fake
28602     _Primitive-add-mem-to-xreg/imm32/next
28603 _Primitive-add-mem-to-xreg:  # (payload primitive)
28604     0x11/imm32/alloc-id:fake:payload
28605     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
28606     0x11/imm32/alloc-id:fake
28607     _string-add/imm32/name
28608     0x11/imm32/alloc-id:fake
28609     Single-float-var-in-mem/imm32/inouts
28610     0x11/imm32/alloc-id:fake
28611     Single-float-var-in-some-register/imm32/outputs
28612     0x11/imm32/alloc-id:fake
28613     _string_f3_0f_58_add/imm32/subx-name
28614     0/imm32/no-rm32
28615     0/imm32/no-r32
28616     0/imm32/no-imm32
28617     0/imm32/no-imm8
28618     0/imm32/no-disp32
28619     1/imm32/xm32-is-first-inout
28620     3/imm32/x32-is-first-output
28621     0x11/imm32/alloc-id:fake
28622     _Primitive-subtract-xreg-from-xreg/imm32/next
28623 # - floating-point subtract
28624 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
28625     0x11/imm32/alloc-id:fake:payload
28626     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
28627     0x11/imm32/alloc-id:fake
28628     _string-subtract/imm32/name
28629     0x11/imm32/alloc-id:fake
28630     Single-float-var-in-some-register/imm32/inouts
28631     0x11/imm32/alloc-id:fake
28632     Single-float-var-in-some-register/imm32/outputs
28633     0x11/imm32/alloc-id:fake
28634     _string_f3_0f_5c_subtract/imm32/subx-name
28635     0/imm32/no-rm32
28636     0/imm32/no-r32
28637     0/imm32/no-imm32
28638     0/imm32/no-imm8
28639     0/imm32/no-disp32
28640     1/imm32/xm32-is-first-inout
28641     3/imm32/x32-is-first-output
28642     0x11/imm32/alloc-id:fake
28643     _Primitive-subtract-mem-from-xreg/imm32/next
28644 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
28645     0x11/imm32/alloc-id:fake:payload
28646     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
28647     0x11/imm32/alloc-id:fake
28648     _string-subtract/imm32/name
28649     0x11/imm32/alloc-id:fake
28650     Single-float-var-in-mem/imm32/inouts
28651     0x11/imm32/alloc-id:fake
28652     Single-float-var-in-some-register/imm32/outputs
28653     0x11/imm32/alloc-id:fake
28654     _string_f3_0f_5c_subtract/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     1/imm32/xm32-is-first-inout
28661     3/imm32/x32-is-first-output
28662     0x11/imm32/alloc-id:fake
28663     _Primitive-multiply-xreg-by-xreg/imm32/next
28664 # - floating-point multiply
28665 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
28666     0x11/imm32/alloc-id:fake:payload
28667     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
28668     0x11/imm32/alloc-id:fake
28669     _string-multiply/imm32/name
28670     0x11/imm32/alloc-id:fake
28671     Single-float-var-in-some-register/imm32/inouts
28672     0x11/imm32/alloc-id:fake
28673     Single-float-var-in-some-register/imm32/outputs
28674     0x11/imm32/alloc-id:fake
28675     _string_f3_0f_59_multiply/imm32/subx-name
28676     0/imm32/no-rm32
28677     0/imm32/no-r32
28678     0/imm32/no-imm32
28679     0/imm32/no-imm8
28680     0/imm32/no-disp32
28681     1/imm32/xm32-is-first-inout
28682     3/imm32/x32-is-first-output
28683     0x11/imm32/alloc-id:fake
28684     _Primitive-multiply-xreg-by-mem/imm32/next
28685 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
28686     0x11/imm32/alloc-id:fake:payload
28687     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
28688     0x11/imm32/alloc-id:fake
28689     _string-multiply/imm32/name
28690     0x11/imm32/alloc-id:fake
28691     Single-float-var-in-mem/imm32/inouts
28692     0x11/imm32/alloc-id:fake
28693     Single-float-var-in-some-register/imm32/outputs
28694     0x11/imm32/alloc-id:fake
28695     _string_f3_0f_59_multiply/imm32/subx-name
28696     0/imm32/no-rm32
28697     0/imm32/no-r32
28698     0/imm32/no-imm32
28699     0/imm32/no-imm8
28700     0/imm32/no-disp32
28701     1/imm32/xm32-is-first-inout
28702     3/imm32/x32-is-first-output
28703     0x11/imm32/alloc-id:fake
28704     _Primitive-divide-xreg-by-xreg/imm32/next
28705 # - floating-point divide
28706 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
28707     0x11/imm32/alloc-id:fake:payload
28708     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
28709     0x11/imm32/alloc-id:fake
28710     _string-divide/imm32/name
28711     0x11/imm32/alloc-id:fake
28712     Single-float-var-in-some-register/imm32/inouts
28713     0x11/imm32/alloc-id:fake
28714     Single-float-var-in-some-register/imm32/outputs
28715     0x11/imm32/alloc-id:fake
28716     _string_f3_0f_5e_divide/imm32/subx-name
28717     0/imm32/no-rm32
28718     0/imm32/no-r32
28719     0/imm32/no-imm32
28720     0/imm32/no-imm8
28721     0/imm32/no-disp32
28722     1/imm32/xm32-is-first-inout
28723     3/imm32/x32-is-first-output
28724     0x11/imm32/alloc-id:fake
28725     _Primitive-divide-xreg-by-mem/imm32/next
28726 _Primitive-divide-xreg-by-mem:  # (payload primitive)
28727     0x11/imm32/alloc-id:fake:payload
28728     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
28729     0x11/imm32/alloc-id:fake
28730     _string-divide/imm32/name
28731     0x11/imm32/alloc-id:fake
28732     Single-float-var-in-mem/imm32/inouts
28733     0x11/imm32/alloc-id:fake
28734     Single-float-var-in-some-register/imm32/outputs
28735     0x11/imm32/alloc-id:fake
28736     _string_f3_0f_5e_divide/imm32/subx-name
28737     0/imm32/no-rm32
28738     0/imm32/no-r32
28739     0/imm32/no-imm32
28740     0/imm32/no-imm8
28741     0/imm32/no-disp32
28742     1/imm32/xm32-is-first-inout
28743     3/imm32/x32-is-first-output
28744     0x11/imm32/alloc-id:fake
28745     _Primitive-max-xreg-with-xreg/imm32/next
28746 # - floating-point maximum
28747 _Primitive-max-xreg-with-xreg:  # (payload primitive)
28748     0x11/imm32/alloc-id:fake:payload
28749     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
28750     0x11/imm32/alloc-id:fake
28751     _string-max/imm32/name
28752     0x11/imm32/alloc-id:fake
28753     Single-float-var-in-some-register/imm32/inouts
28754     0x11/imm32/alloc-id:fake
28755     Single-float-var-in-some-register/imm32/outputs
28756     0x11/imm32/alloc-id:fake
28757     _string_f3_0f_5f_max/imm32/subx-name
28758     0/imm32/no-rm32
28759     0/imm32/no-r32
28760     0/imm32/no-imm32
28761     0/imm32/no-imm8
28762     0/imm32/no-disp32
28763     1/imm32/xm32-is-first-inout
28764     3/imm32/x32-is-first-output
28765     0x11/imm32/alloc-id:fake
28766     _Primitive-max-xreg-with-mem/imm32/next
28767 _Primitive-max-xreg-with-mem:  # (payload primitive)
28768     0x11/imm32/alloc-id:fake:payload
28769     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
28770     0x11/imm32/alloc-id:fake
28771     _string-max/imm32/name
28772     0x11/imm32/alloc-id:fake
28773     Single-float-var-in-mem/imm32/inouts
28774     0x11/imm32/alloc-id:fake
28775     Single-float-var-in-some-register/imm32/outputs
28776     0x11/imm32/alloc-id:fake
28777     _string_f3_0f_5f_max/imm32/subx-name
28778     0/imm32/no-rm32
28779     0/imm32/no-r32
28780     0/imm32/no-imm32
28781     0/imm32/no-imm8
28782     0/imm32/no-disp32
28783     1/imm32/xm32-is-first-inout
28784     3/imm32/x32-is-first-output
28785     0x11/imm32/alloc-id:fake
28786     _Primitive-min-xreg-with-xreg/imm32/next
28787 # - floating-point minimum
28788 _Primitive-min-xreg-with-xreg:  # (payload primitive)
28789     0x11/imm32/alloc-id:fake:payload
28790     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
28791     0x11/imm32/alloc-id:fake
28792     _string-min/imm32/name
28793     0x11/imm32/alloc-id:fake
28794     Single-float-var-in-some-register/imm32/inouts
28795     0x11/imm32/alloc-id:fake
28796     Single-float-var-in-some-register/imm32/outputs
28797     0x11/imm32/alloc-id:fake
28798     _string_f3_0f_5d_min/imm32/subx-name
28799     0/imm32/no-rm32
28800     0/imm32/no-r32
28801     0/imm32/no-imm32
28802     0/imm32/no-imm8
28803     0/imm32/no-disp32
28804     1/imm32/xm32-is-first-inout
28805     3/imm32/x32-is-first-output
28806     0x11/imm32/alloc-id:fake
28807     _Primitive-min-xreg-with-mem/imm32/next
28808 _Primitive-min-xreg-with-mem:  # (payload primitive)
28809     0x11/imm32/alloc-id:fake:payload
28810     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
28811     0x11/imm32/alloc-id:fake
28812     _string-min/imm32/name
28813     0x11/imm32/alloc-id:fake
28814     Single-float-var-in-mem/imm32/inouts
28815     0x11/imm32/alloc-id:fake
28816     Single-float-var-in-some-register/imm32/outputs
28817     0x11/imm32/alloc-id:fake
28818     _string_f3_0f_5d_min/imm32/subx-name
28819     0/imm32/no-rm32
28820     0/imm32/no-r32
28821     0/imm32/no-imm32
28822     0/imm32/no-imm8
28823     0/imm32/no-disp32
28824     1/imm32/xm32-is-first-inout
28825     3/imm32/x32-is-first-output
28826     0x11/imm32/alloc-id:fake
28827     _Primitive-reciprocal-xreg-to-xreg/imm32/next
28828 # - floating-point reciprocal
28829 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
28830     0x11/imm32/alloc-id:fake:payload
28831     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
28832     0x11/imm32/alloc-id:fake
28833     _string-reciprocal/imm32/name
28834     0x11/imm32/alloc-id:fake
28835     Single-float-var-in-some-register/imm32/inouts
28836     0x11/imm32/alloc-id:fake
28837     Single-float-var-in-some-register/imm32/outputs
28838     0x11/imm32/alloc-id:fake
28839     _string_f3_0f_53_reciprocal/imm32/subx-name
28840     0/imm32/no-rm32
28841     0/imm32/no-r32
28842     0/imm32/no-imm32
28843     0/imm32/no-imm8
28844     0/imm32/no-disp32
28845     1/imm32/xm32-is-first-inout
28846     3/imm32/x32-is-first-output
28847     0x11/imm32/alloc-id:fake
28848     _Primitive-reciprocal-mem-to-xreg/imm32/next
28849 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
28850     0x11/imm32/alloc-id:fake:payload
28851     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
28852     0x11/imm32/alloc-id:fake
28853     _string-reciprocal/imm32/name
28854     0x11/imm32/alloc-id:fake
28855     Single-float-var-in-mem/imm32/inouts
28856     0x11/imm32/alloc-id:fake
28857     Single-float-var-in-some-register/imm32/outputs
28858     0x11/imm32/alloc-id:fake
28859     _string_f3_0f_53_reciprocal/imm32/subx-name
28860     0/imm32/no-rm32
28861     0/imm32/no-r32
28862     0/imm32/no-imm32
28863     0/imm32/no-imm8
28864     0/imm32/no-disp32
28865     1/imm32/xm32-is-first-inout
28866     3/imm32/x32-is-first-output
28867     0x11/imm32/alloc-id:fake
28868     _Primitive-square-root-xreg-to-xreg/imm32/next
28869 # - floating-point square root
28870 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
28871     0x11/imm32/alloc-id:fake:payload
28872     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
28873     0x11/imm32/alloc-id:fake
28874     _string-square-root/imm32/name
28875     0x11/imm32/alloc-id:fake
28876     Single-float-var-in-some-register/imm32/inouts
28877     0x11/imm32/alloc-id:fake
28878     Single-float-var-in-some-register/imm32/outputs
28879     0x11/imm32/alloc-id:fake
28880     _string_f3_0f_51_square_root/imm32/subx-name
28881     0/imm32/no-rm32
28882     0/imm32/no-r32
28883     0/imm32/no-imm32
28884     0/imm32/no-imm8
28885     0/imm32/no-disp32
28886     1/imm32/xm32-is-first-inout
28887     3/imm32/x32-is-first-output
28888     0x11/imm32/alloc-id:fake
28889     _Primitive-square-root-mem-to-xreg/imm32/next
28890 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
28891     0x11/imm32/alloc-id:fake:payload
28892     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
28893     0x11/imm32/alloc-id:fake
28894     _string-square-root/imm32/name
28895     0x11/imm32/alloc-id:fake
28896     Single-float-var-in-mem/imm32/inouts
28897     0x11/imm32/alloc-id:fake
28898     Single-float-var-in-some-register/imm32/outputs
28899     0x11/imm32/alloc-id:fake
28900     _string_f3_0f_51_square_root/imm32/subx-name
28901     0/imm32/no-rm32
28902     0/imm32/no-r32
28903     0/imm32/no-imm32
28904     0/imm32/no-imm8
28905     0/imm32/no-disp32
28906     1/imm32/xm32-is-first-inout
28907     3/imm32/x32-is-first-output
28908     0x11/imm32/alloc-id:fake
28909     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
28910 # - floating-point inverse square root 1/sqrt(x)
28911 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
28912     0x11/imm32/alloc-id:fake:payload
28913     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
28914     0x11/imm32/alloc-id:fake
28915     _string-inverse-square-root/imm32/name
28916     0x11/imm32/alloc-id:fake
28917     Single-float-var-in-some-register/imm32/inouts
28918     0x11/imm32/alloc-id:fake
28919     Single-float-var-in-some-register/imm32/outputs
28920     0x11/imm32/alloc-id:fake
28921     _string_f3_0f_52_inverse_square_root/imm32/subx-name
28922     0/imm32/no-rm32
28923     0/imm32/no-r32
28924     0/imm32/no-imm32
28925     0/imm32/no-imm8
28926     0/imm32/no-disp32
28927     1/imm32/xm32-is-first-inout
28928     3/imm32/x32-is-first-output
28929     0x11/imm32/alloc-id:fake
28930     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
28931 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
28932     0x11/imm32/alloc-id:fake:payload
28933     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
28934     0x11/imm32/alloc-id:fake
28935     _string-inverse-square-root/imm32/name
28936     0x11/imm32/alloc-id:fake
28937     Single-float-var-in-mem/imm32/inouts
28938     0x11/imm32/alloc-id:fake
28939     Single-float-var-in-some-register/imm32/outputs
28940     0x11/imm32/alloc-id:fake
28941     _string_f3_0f_52_inverse_square_root/imm32/subx-name
28942     0/imm32/no-rm32
28943     0/imm32/no-r32
28944     0/imm32/no-imm32
28945     0/imm32/no-imm8
28946     0/imm32/no-disp32
28947     1/imm32/xm32-is-first-inout
28948     3/imm32/x32-is-first-output
28949     0x11/imm32/alloc-id:fake
28950     _Primitive-compare-xreg-with-xreg/imm32/next
28951 # - floating-point compare
28952 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
28953     0x11/imm32/alloc-id:fake:payload
28954     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
28955     0x11/imm32/alloc-id:fake
28956     _string-compare/imm32/name
28957     0x11/imm32/alloc-id:fake
28958     Two-float-args-in-regs/imm32/inouts
28959     0/imm32/no-outputs
28960     0/imm32/no-outputs
28961     0x11/imm32/alloc-id:fake
28962     _string_0f_2f_compare/imm32/subx-name
28963     0/imm32/no-rm32
28964     0/imm32/no-r32
28965     0/imm32/no-imm32
28966     0/imm32/no-imm8
28967     0/imm32/no-disp32
28968     1/imm32/xm32-is-first-inout
28969     2/imm32/x32-is-second-inout
28970     0x11/imm32/alloc-id:fake
28971     _Primitive-compare-xreg-with-mem/imm32/next
28972 _Primitive-compare-xreg-with-mem:  # (payload primitive)
28973     0x11/imm32/alloc-id:fake:payload
28974     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
28975     0x11/imm32/alloc-id:fake
28976     _string-compare/imm32/name
28977     0x11/imm32/alloc-id:fake
28978     Two-args-float-reg-float-stack/imm32/inouts
28979     0/imm32/no-outputs
28980     0/imm32/no-outputs
28981     0x11/imm32/alloc-id:fake
28982     _string_0f_2f_compare/imm32/subx-name
28983     0/imm32/no-rm32
28984     0/imm32/no-r32
28985     0/imm32/no-imm32
28986     0/imm32/no-imm8
28987     0/imm32/no-disp32
28988     2/imm32/xm32-is-second-inout
28989     1/imm32/x32-is-first-inout
28990     0x11/imm32/alloc-id:fake
28991     _Primitive-break-if-addr</imm32/next
28992 # - branches
28993 _Primitive-break-if-addr<:  # (payload primitive)
28994     0x11/imm32/alloc-id:fake:payload
28995     0x11/imm32/alloc-id:fake
28996     _string-break-if-addr</imm32/name
28997     0/imm32/no-inouts
28998     0/imm32/no-inouts
28999     0/imm32/no-outputs
29000     0/imm32/no-outputs
29001     0x11/imm32/alloc-id:fake
29002     _string_0f_82_jump_break/imm32/subx-name
29003     0/imm32/no-rm32
29004     0/imm32/no-r32
29005     0/imm32/no-imm32
29006     0/imm32/no-imm8
29007     0/imm32/no-disp32
29008     0/imm32/no-xm32
29009     0/imm32/no-x32
29010     0x11/imm32/alloc-id:fake
29011     _Primitive-break-if-addr>=/imm32/next
29012 _Primitive-break-if-addr>=:  # (payload primitive)
29013     0x11/imm32/alloc-id:fake:payload
29014     0x11/imm32/alloc-id:fake
29015     _string-break-if-addr>=/imm32/name
29016     0/imm32/no-inouts
29017     0/imm32/no-inouts
29018     0/imm32/no-outputs
29019     0/imm32/no-outputs
29020     0x11/imm32/alloc-id:fake
29021     _string_0f_83_jump_break/imm32/subx-name
29022     0/imm32/no-rm32
29023     0/imm32/no-r32
29024     0/imm32/no-imm32
29025     0/imm32/no-imm8
29026     0/imm32/no-disp32
29027     0/imm32/no-xm32
29028     0/imm32/no-x32
29029     0x11/imm32/alloc-id:fake
29030     _Primitive-break-if-=/imm32/next
29031 _Primitive-break-if-=:  # (payload primitive)
29032     0x11/imm32/alloc-id:fake:payload
29033     0x11/imm32/alloc-id:fake
29034     _string-break-if-=/imm32/name
29035     0/imm32/no-inouts
29036     0/imm32/no-inouts
29037     0/imm32/no-outputs
29038     0/imm32/no-outputs
29039     0x11/imm32/alloc-id:fake
29040     _string_0f_84_jump_break/imm32/subx-name
29041     0/imm32/no-rm32
29042     0/imm32/no-r32
29043     0/imm32/no-imm32
29044     0/imm32/no-imm8
29045     0/imm32/no-disp32
29046     0/imm32/no-xm32
29047     0/imm32/no-x32
29048     0x11/imm32/alloc-id:fake
29049     _Primitive-break-if-!=/imm32/next
29050 _Primitive-break-if-!=:  # (payload primitive)
29051     0x11/imm32/alloc-id:fake:payload
29052     0x11/imm32/alloc-id:fake
29053     _string-break-if-!=/imm32/name
29054     0/imm32/no-inouts
29055     0/imm32/no-inouts
29056     0/imm32/no-outputs
29057     0/imm32/no-outputs
29058     0x11/imm32/alloc-id:fake
29059     _string_0f_85_jump_break/imm32/subx-name
29060     0/imm32/no-rm32
29061     0/imm32/no-r32
29062     0/imm32/no-imm32
29063     0/imm32/no-imm8
29064     0/imm32/no-disp32
29065     0/imm32/no-xm32
29066     0/imm32/no-x32
29067     0x11/imm32/alloc-id:fake
29068     _Primitive-break-if-addr<=/imm32/next
29069 _Primitive-break-if-addr<=:  # (payload primitive)
29070     0x11/imm32/alloc-id:fake:payload
29071     0x11/imm32/alloc-id:fake
29072     _string-break-if-addr<=/imm32/name
29073     0/imm32/no-inouts
29074     0/imm32/no-inouts
29075     0/imm32/no-outputs
29076     0/imm32/no-outputs
29077     0x11/imm32/alloc-id:fake
29078     _string_0f_86_jump_break/imm32/subx-name
29079     0/imm32/no-rm32
29080     0/imm32/no-r32
29081     0/imm32/no-imm32
29082     0/imm32/no-imm8
29083     0/imm32/no-disp32
29084     0/imm32/no-xm32
29085     0/imm32/no-x32
29086     0x11/imm32/alloc-id:fake
29087     _Primitive-break-if-addr>/imm32/next
29088 _Primitive-break-if-addr>:  # (payload primitive)
29089     0x11/imm32/alloc-id:fake:payload
29090     0x11/imm32/alloc-id:fake
29091     _string-break-if-addr>/imm32/name
29092     0/imm32/no-inouts
29093     0/imm32/no-inouts
29094     0/imm32/no-outputs
29095     0/imm32/no-outputs
29096     0x11/imm32/alloc-id:fake
29097     _string_0f_87_jump_break/imm32/subx-name
29098     0/imm32/no-rm32
29099     0/imm32/no-r32
29100     0/imm32/no-imm32
29101     0/imm32/no-imm8
29102     0/imm32/no-disp32
29103     0/imm32/no-xm32
29104     0/imm32/no-x32
29105     0x11/imm32/alloc-id:fake
29106     _Primitive-break-if-</imm32/next
29107 _Primitive-break-if-<:  # (payload primitive)
29108     0x11/imm32/alloc-id:fake:payload
29109     0x11/imm32/alloc-id:fake
29110     _string-break-if-</imm32/name
29111     0/imm32/no-inouts
29112     0/imm32/no-inouts
29113     0/imm32/no-outputs
29114     0/imm32/no-outputs
29115     0x11/imm32/alloc-id:fake
29116     _string_0f_8c_jump_break/imm32/subx-name
29117     0/imm32/no-rm32
29118     0/imm32/no-r32
29119     0/imm32/no-imm32
29120     0/imm32/no-imm8
29121     0/imm32/no-disp32
29122     0/imm32/no-xm32
29123     0/imm32/no-x32
29124     0x11/imm32/alloc-id:fake
29125     _Primitive-break-if->=/imm32/next
29126 _Primitive-break-if->=:  # (payload primitive)
29127     0x11/imm32/alloc-id:fake:payload
29128     0x11/imm32/alloc-id:fake
29129     _string-break-if->=/imm32/name
29130     0/imm32/no-inouts
29131     0/imm32/no-inouts
29132     0/imm32/no-outputs
29133     0/imm32/no-outputs
29134     0x11/imm32/alloc-id:fake
29135     _string_0f_8d_jump_break/imm32/subx-name
29136     0/imm32/no-rm32
29137     0/imm32/no-r32
29138     0/imm32/no-imm32
29139     0/imm32/no-imm8
29140     0/imm32/no-disp32
29141     0/imm32/no-xm32
29142     0/imm32/no-x32
29143     0x11/imm32/alloc-id:fake
29144     _Primitive-break-if-<=/imm32/next
29145 _Primitive-break-if-<=:  # (payload primitive)
29146     0x11/imm32/alloc-id:fake:payload
29147     0x11/imm32/alloc-id:fake
29148     _string-break-if-<=/imm32/name
29149     0/imm32/no-inouts
29150     0/imm32/no-inouts
29151     0/imm32/no-outputs
29152     0/imm32/no-outputs
29153     0x11/imm32/alloc-id:fake
29154     _string_0f_8e_jump_break/imm32/subx-name
29155     0/imm32/no-rm32
29156     0/imm32/no-r32
29157     0/imm32/no-imm32
29158     0/imm32/no-imm8
29159     0/imm32/no-disp32
29160     0/imm32/no-xm32
29161     0/imm32/no-x32
29162     0x11/imm32/alloc-id:fake
29163     _Primitive-break-if->/imm32/next
29164 _Primitive-break-if->:  # (payload primitive)
29165     0x11/imm32/alloc-id:fake:payload
29166     0x11/imm32/alloc-id:fake
29167     _string-break-if->/imm32/name
29168     0/imm32/no-inouts
29169     0/imm32/no-inouts
29170     0/imm32/no-outputs
29171     0/imm32/no-outputs
29172     0x11/imm32/alloc-id:fake
29173     _string_0f_8f_jump_break/imm32/subx-name
29174     0/imm32/no-rm32
29175     0/imm32/no-r32
29176     0/imm32/no-imm32
29177     0/imm32/no-imm8
29178     0/imm32/no-disp32
29179     0/imm32/no-xm32
29180     0/imm32/no-x32
29181     0x11/imm32/alloc-id:fake
29182     _Primitive-break/imm32/next
29183 _Primitive-break:  # (payload primitive)
29184     0x11/imm32/alloc-id:fake:payload
29185     0x11/imm32/alloc-id:fake
29186     _string-break/imm32/name
29187     0/imm32/no-inouts
29188     0/imm32/no-inouts
29189     0/imm32/no-outputs
29190     0/imm32/no-outputs
29191     0x11/imm32/alloc-id:fake
29192     _string_e9_jump_break/imm32/subx-name
29193     0/imm32/no-rm32
29194     0/imm32/no-r32
29195     0/imm32/no-imm32
29196     0/imm32/no-imm8
29197     0/imm32/no-disp32
29198     0/imm32/no-xm32
29199     0/imm32/no-x32
29200     0x11/imm32/alloc-id:fake
29201     _Primitive-loop-if-addr</imm32/next
29202 _Primitive-loop-if-addr<:  # (payload primitive)
29203     0x11/imm32/alloc-id:fake:payload
29204     0x11/imm32/alloc-id:fake
29205     _string-loop-if-addr</imm32/name
29206     0/imm32/no-inouts
29207     0/imm32/no-inouts
29208     0/imm32/no-outputs
29209     0/imm32/no-outputs
29210     0x11/imm32/alloc-id:fake
29211     _string_0f_82_jump_loop/imm32/subx-name
29212     0/imm32/no-rm32
29213     0/imm32/no-r32
29214     0/imm32/no-imm32
29215     0/imm32/no-imm8
29216     0/imm32/no-disp32
29217     0/imm32/no-xm32
29218     0/imm32/no-x32
29219     0x11/imm32/alloc-id:fake
29220     _Primitive-loop-if-addr>=/imm32/next
29221 _Primitive-loop-if-addr>=:  # (payload primitive)
29222     0x11/imm32/alloc-id:fake:payload
29223     0x11/imm32/alloc-id:fake
29224     _string-loop-if-addr>=/imm32/name
29225     0/imm32/no-inouts
29226     0/imm32/no-inouts
29227     0/imm32/no-outputs
29228     0/imm32/no-outputs
29229     0x11/imm32/alloc-id:fake
29230     _string_0f_83_jump_loop/imm32/subx-name
29231     0/imm32/no-rm32
29232     0/imm32/no-r32
29233     0/imm32/no-imm32
29234     0/imm32/no-imm8
29235     0/imm32/no-disp32
29236     0/imm32/no-xm32
29237     0/imm32/no-x32
29238     0x11/imm32/alloc-id:fake
29239     _Primitive-loop-if-=/imm32/next
29240 _Primitive-loop-if-=:  # (payload primitive)
29241     0x11/imm32/alloc-id:fake:payload
29242     0x11/imm32/alloc-id:fake
29243     _string-loop-if-=/imm32/name
29244     0/imm32/no-inouts
29245     0/imm32/no-inouts
29246     0/imm32/no-outputs
29247     0/imm32/no-outputs
29248     0x11/imm32/alloc-id:fake
29249     _string_0f_84_jump_loop/imm32/subx-name
29250     0/imm32/no-rm32
29251     0/imm32/no-r32
29252     0/imm32/no-imm32
29253     0/imm32/no-imm8
29254     0/imm32/no-disp32
29255     0/imm32/no-xm32
29256     0/imm32/no-x32
29257     0x11/imm32/alloc-id:fake
29258     _Primitive-loop-if-!=/imm32/next
29259 _Primitive-loop-if-!=:  # (payload primitive)
29260     0x11/imm32/alloc-id:fake:payload
29261     0x11/imm32/alloc-id:fake
29262     _string-loop-if-!=/imm32/name
29263     0/imm32/no-inouts
29264     0/imm32/no-inouts
29265     0/imm32/no-outputs
29266     0/imm32/no-outputs
29267     0x11/imm32/alloc-id:fake
29268     _string_0f_85_jump_loop/imm32/subx-name
29269     0/imm32/no-rm32
29270     0/imm32/no-r32
29271     0/imm32/no-imm32
29272     0/imm32/no-imm8
29273     0/imm32/no-disp32
29274     0/imm32/no-xm32
29275     0/imm32/no-x32
29276     0x11/imm32/alloc-id:fake
29277     _Primitive-loop-if-addr<=/imm32/next
29278 _Primitive-loop-if-addr<=:  # (payload primitive)
29279     0x11/imm32/alloc-id:fake:payload
29280     0x11/imm32/alloc-id:fake
29281     _string-loop-if-addr<=/imm32/name
29282     0/imm32/no-inouts
29283     0/imm32/no-inouts
29284     0/imm32/no-outputs
29285     0/imm32/no-outputs
29286     0x11/imm32/alloc-id:fake
29287     _string_0f_86_jump_loop/imm32/subx-name
29288     0/imm32/no-rm32
29289     0/imm32/no-r32
29290     0/imm32/no-imm32
29291     0/imm32/no-imm8
29292     0/imm32/no-disp32
29293     0/imm32/no-xm32
29294     0/imm32/no-x32
29295     0x11/imm32/alloc-id:fake
29296     _Primitive-loop-if-addr>/imm32/next
29297 _Primitive-loop-if-addr>:  # (payload primitive)
29298     0x11/imm32/alloc-id:fake:payload
29299     0x11/imm32/alloc-id:fake
29300     _string-loop-if-addr>/imm32/name
29301     0/imm32/no-inouts
29302     0/imm32/no-inouts
29303     0/imm32/no-outputs
29304     0/imm32/no-outputs
29305     0x11/imm32/alloc-id:fake
29306     _string_0f_87_jump_loop/imm32/subx-name
29307     0/imm32/no-rm32
29308     0/imm32/no-r32
29309     0/imm32/no-imm32
29310     0/imm32/no-imm8
29311     0/imm32/no-disp32
29312     0/imm32/no-xm32
29313     0/imm32/no-x32
29314     0x11/imm32/alloc-id:fake
29315     _Primitive-loop-if-</imm32/next
29316 _Primitive-loop-if-<:  # (payload primitive)
29317     0x11/imm32/alloc-id:fake:payload
29318     0x11/imm32/alloc-id:fake
29319     _string-loop-if-</imm32/name
29320     0/imm32/no-inouts
29321     0/imm32/no-inouts
29322     0/imm32/no-outputs
29323     0/imm32/no-outputs
29324     0x11/imm32/alloc-id:fake
29325     _string_0f_8c_jump_loop/imm32/subx-name
29326     0/imm32/no-rm32
29327     0/imm32/no-r32
29328     0/imm32/no-imm32
29329     0/imm32/no-imm8
29330     0/imm32/no-disp32
29331     0/imm32/no-xm32
29332     0/imm32/no-x32
29333     0x11/imm32/alloc-id:fake
29334     _Primitive-loop-if->=/imm32/next
29335 _Primitive-loop-if->=:  # (payload primitive)
29336     0x11/imm32/alloc-id:fake:payload
29337     0x11/imm32/alloc-id:fake
29338     _string-loop-if->=/imm32/name
29339     0/imm32/no-inouts
29340     0/imm32/no-inouts
29341     0/imm32/no-outputs
29342     0/imm32/no-outputs
29343     0x11/imm32/alloc-id:fake
29344     _string_0f_8d_jump_loop/imm32/subx-name
29345     0/imm32/no-rm32
29346     0/imm32/no-r32
29347     0/imm32/no-imm32
29348     0/imm32/no-imm8
29349     0/imm32/no-disp32
29350     0/imm32/no-xm32
29351     0/imm32/no-x32
29352     0x11/imm32/alloc-id:fake
29353     _Primitive-loop-if-<=/imm32/next
29354 _Primitive-loop-if-<=:  # (payload primitive)
29355     0x11/imm32/alloc-id:fake:payload
29356     0x11/imm32/alloc-id:fake
29357     _string-loop-if-<=/imm32/name
29358     0/imm32/no-inouts
29359     0/imm32/no-inouts
29360     0/imm32/no-outputs
29361     0/imm32/no-outputs
29362     0x11/imm32/alloc-id:fake
29363     _string_0f_8e_jump_loop/imm32/subx-name
29364     0/imm32/no-rm32
29365     0/imm32/no-r32
29366     0/imm32/no-imm32
29367     0/imm32/no-imm8
29368     0/imm32/no-disp32
29369     0/imm32/no-xm32
29370     0/imm32/no-x32
29371     0x11/imm32/alloc-id:fake
29372     _Primitive-loop-if->/imm32/next
29373 _Primitive-loop-if->:  # (payload primitive)
29374     0x11/imm32/alloc-id:fake:payload
29375     0x11/imm32/alloc-id:fake
29376     _string-loop-if->/imm32/name
29377     0/imm32/no-inouts
29378     0/imm32/no-inouts
29379     0/imm32/no-outputs
29380     0/imm32/no-outputs
29381     0x11/imm32/alloc-id:fake
29382     _string_0f_8f_jump_loop/imm32/subx-name
29383     0/imm32/no-rm32
29384     0/imm32/no-r32
29385     0/imm32/no-imm32
29386     0/imm32/no-imm8
29387     0/imm32/no-disp32
29388     0/imm32/no-xm32
29389     0/imm32/no-x32
29390     0x11/imm32/alloc-id:fake
29391     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
29392 _Primitive-loop:  # (payload primitive)
29393     0x11/imm32/alloc-id:fake:payload
29394     0x11/imm32/alloc-id:fake
29395     _string-loop/imm32/name
29396     0/imm32/no-inouts
29397     0/imm32/no-inouts
29398     0/imm32/no-outputs
29399     0/imm32/no-outputs
29400     0x11/imm32/alloc-id:fake
29401     _string_e9_jump_loop/imm32/subx-name
29402     0/imm32/no-rm32
29403     0/imm32/no-r32
29404     0/imm32/no-imm32
29405     0/imm32/no-imm8
29406     0/imm32/no-disp32
29407     0/imm32/no-xm32
29408     0/imm32/no-x32
29409     0x11/imm32/alloc-id:fake
29410     _Primitive-break-if-addr<-named/imm32/next
29411 # - branches to named blocks
29412 _Primitive-break-if-addr<-named:  # (payload primitive)
29413     0x11/imm32/alloc-id:fake:payload
29414     0x11/imm32/alloc-id:fake
29415     _string-break-if-addr</imm32/name
29416     0x11/imm32/alloc-id:fake
29417     Single-lit-var/imm32/inouts
29418     0/imm32/no-outputs
29419     0/imm32/no-outputs
29420     0x11/imm32/alloc-id:fake
29421     _string_0f_82_jump_label/imm32/subx-name
29422     0/imm32/no-rm32
29423     0/imm32/no-r32
29424     0/imm32/no-imm32
29425     0/imm32/no-imm8
29426     1/imm32/disp32-is-first-inout
29427     0/imm32/no-xm32
29428     0/imm32/no-x32
29429     0x11/imm32/alloc-id:fake
29430     _Primitive-break-if-addr>=-named/imm32/next
29431 _Primitive-break-if-addr>=-named:  # (payload primitive)
29432     0x11/imm32/alloc-id:fake:payload
29433     0x11/imm32/alloc-id:fake
29434     _string-break-if-addr>=/imm32/name
29435     0x11/imm32/alloc-id:fake
29436     Single-lit-var/imm32/inouts
29437     0/imm32/no-outputs
29438     0/imm32/no-outputs
29439     0x11/imm32/alloc-id:fake
29440     _string_0f_83_jump_label/imm32/subx-name
29441     0/imm32/no-rm32
29442     0/imm32/no-r32
29443     0/imm32/no-imm32
29444     0/imm32/no-imm8
29445     1/imm32/disp32-is-first-inout
29446     0/imm32/no-xm32
29447     0/imm32/no-x32
29448     0x11/imm32/alloc-id:fake
29449     _Primitive-break-if-=-named/imm32/next
29450 _Primitive-break-if-=-named:  # (payload primitive)
29451     0x11/imm32/alloc-id:fake:payload
29452     0x11/imm32/alloc-id:fake
29453     _string-break-if-=/imm32/name
29454     0x11/imm32/alloc-id:fake
29455     Single-lit-var/imm32/inouts
29456     0/imm32/no-outputs
29457     0/imm32/no-outputs
29458     0x11/imm32/alloc-id:fake
29459     _string_0f_84_jump_label/imm32/subx-name
29460     0/imm32/no-rm32
29461     0/imm32/no-r32
29462     0/imm32/no-imm32
29463     0/imm32/no-imm8
29464     1/imm32/disp32-is-first-inout
29465     0/imm32/no-xm32
29466     0/imm32/no-x32
29467     0x11/imm32/alloc-id:fake
29468     _Primitive-break-if-!=-named/imm32/next
29469 _Primitive-break-if-!=-named:  # (payload primitive)
29470     0x11/imm32/alloc-id:fake:payload
29471     0x11/imm32/alloc-id:fake
29472     _string-break-if-!=/imm32/name
29473     0x11/imm32/alloc-id:fake
29474     Single-lit-var/imm32/inouts
29475     0/imm32/no-outputs
29476     0/imm32/no-outputs
29477     0x11/imm32/alloc-id:fake
29478     _string_0f_85_jump_label/imm32/subx-name
29479     0/imm32/no-rm32
29480     0/imm32/no-r32
29481     0/imm32/no-imm32
29482     0/imm32/no-imm8
29483     1/imm32/disp32-is-first-inout
29484     0/imm32/no-xm32
29485     0/imm32/no-x32
29486     0x11/imm32/alloc-id:fake
29487     _Primitive-break-if-addr<=-named/imm32/next
29488 _Primitive-break-if-addr<=-named:  # (payload primitive)
29489     0x11/imm32/alloc-id:fake:payload
29490     0x11/imm32/alloc-id:fake
29491     _string-break-if-addr<=/imm32/name
29492     0x11/imm32/alloc-id:fake
29493     Single-lit-var/imm32/inouts
29494     0/imm32/no-outputs
29495     0/imm32/no-outputs
29496     0x11/imm32/alloc-id:fake
29497     _string_0f_86_jump_label/imm32/subx-name
29498     0/imm32/no-rm32
29499     0/imm32/no-r32
29500     0/imm32/no-imm32
29501     0/imm32/no-imm8
29502     1/imm32/disp32-is-first-inout
29503     0/imm32/no-xm32
29504     0/imm32/no-x32
29505     0x11/imm32/alloc-id:fake
29506     _Primitive-break-if-addr>-named/imm32/next
29507 _Primitive-break-if-addr>-named:  # (payload primitive)
29508     0x11/imm32/alloc-id:fake:payload
29509     0x11/imm32/alloc-id:fake
29510     _string-break-if-addr>/imm32/name
29511     0x11/imm32/alloc-id:fake
29512     Single-lit-var/imm32/inouts
29513     0/imm32/no-outputs
29514     0/imm32/no-outputs
29515     0x11/imm32/alloc-id:fake
29516     _string_0f_87_jump_label/imm32/subx-name
29517     0/imm32/no-rm32
29518     0/imm32/no-r32
29519     0/imm32/no-imm32
29520     0/imm32/no-imm8
29521     1/imm32/disp32-is-first-inout
29522     0/imm32/no-xm32
29523     0/imm32/no-x32
29524     0x11/imm32/alloc-id:fake
29525     _Primitive-break-if-<-named/imm32/next
29526 _Primitive-break-if-<-named:  # (payload primitive)
29527     0x11/imm32/alloc-id:fake:payload
29528     0x11/imm32/alloc-id:fake
29529     _string-break-if-</imm32/name
29530     0x11/imm32/alloc-id:fake
29531     Single-lit-var/imm32/inouts
29532     0/imm32/no-outputs
29533     0/imm32/no-outputs
29534     0x11/imm32/alloc-id:fake
29535     _string_0f_8c_jump_label/imm32/subx-name
29536     0/imm32/no-rm32
29537     0/imm32/no-r32
29538     0/imm32/no-imm32
29539     0/imm32/no-imm8
29540     1/imm32/disp32-is-first-inout
29541     0/imm32/no-xm32
29542     0/imm32/no-x32
29543     0x11/imm32/alloc-id:fake
29544     _Primitive-break-if->=-named/imm32/next
29545 _Primitive-break-if->=-named:  # (payload primitive)
29546     0x11/imm32/alloc-id:fake:payload
29547     0x11/imm32/alloc-id:fake
29548     _string-break-if->=/imm32/name
29549     0x11/imm32/alloc-id:fake
29550     Single-lit-var/imm32/inouts
29551     0/imm32/no-outputs
29552     0/imm32/no-outputs
29553     0x11/imm32/alloc-id:fake
29554     _string_0f_8d_jump_label/imm32/subx-name
29555     0/imm32/no-rm32
29556     0/imm32/no-r32
29557     0/imm32/no-imm32
29558     0/imm32/no-imm8
29559     1/imm32/disp32-is-first-inout
29560     0/imm32/no-xm32
29561     0/imm32/no-x32
29562     0x11/imm32/alloc-id:fake
29563     _Primitive-break-if-<=-named/imm32/next
29564 _Primitive-break-if-<=-named:  # (payload primitive)
29565     0x11/imm32/alloc-id:fake:payload
29566     0x11/imm32/alloc-id:fake
29567     _string-break-if-<=/imm32/name
29568     0x11/imm32/alloc-id:fake
29569     Single-lit-var/imm32/inouts
29570     0/imm32/no-outputs
29571     0/imm32/no-outputs
29572     0x11/imm32/alloc-id:fake
29573     _string_0f_8e_jump_label/imm32/subx-name
29574     0/imm32/no-rm32
29575     0/imm32/no-r32
29576     0/imm32/no-imm32
29577     0/imm32/no-imm8
29578     1/imm32/disp32-is-first-inout
29579     0/imm32/no-xm32
29580     0/imm32/no-x32
29581     0x11/imm32/alloc-id:fake
29582     _Primitive-break-if->-named/imm32/next
29583 _Primitive-break-if->-named:  # (payload primitive)
29584     0x11/imm32/alloc-id:fake:payload
29585     0x11/imm32/alloc-id:fake
29586     _string-break-if->/imm32/name
29587     0x11/imm32/alloc-id:fake
29588     Single-lit-var/imm32/inouts
29589     0/imm32/no-outputs
29590     0/imm32/no-outputs
29591     0x11/imm32/alloc-id:fake
29592     _string_0f_8f_jump_label/imm32/subx-name
29593     0/imm32/no-rm32
29594     0/imm32/no-r32
29595     0/imm32/no-imm32
29596     0/imm32/no-imm8
29597     1/imm32/disp32-is-first-inout
29598     0/imm32/no-xm32
29599     0/imm32/no-x32
29600     0x11/imm32/alloc-id:fake
29601     _Primitive-break-named/imm32/next
29602 _Primitive-break-named:  # (payload primitive)
29603     0x11/imm32/alloc-id:fake:payload
29604     0x11/imm32/alloc-id:fake
29605     _string-break/imm32/name
29606     0x11/imm32/alloc-id:fake
29607     Single-lit-var/imm32/inouts
29608     0/imm32/no-outputs
29609     0/imm32/no-outputs
29610     0x11/imm32/alloc-id:fake
29611     _string_e9_jump_label/imm32/subx-name
29612     0/imm32/no-rm32
29613     0/imm32/no-r32
29614     0/imm32/no-imm32
29615     0/imm32/no-imm8
29616     1/imm32/disp32-is-first-inout
29617     0/imm32/no-xm32
29618     0/imm32/no-x32
29619     0x11/imm32/alloc-id:fake
29620     _Primitive-loop-if-addr<-named/imm32/next
29621 _Primitive-loop-if-addr<-named:  # (payload primitive)
29622     0x11/imm32/alloc-id:fake:payload
29623     0x11/imm32/alloc-id:fake
29624     _string-loop-if-addr</imm32/name
29625     0x11/imm32/alloc-id:fake
29626     Single-lit-var/imm32/inouts
29627     0/imm32/no-outputs
29628     0/imm32/no-outputs
29629     0x11/imm32/alloc-id:fake
29630     _string_0f_82_jump_label/imm32/subx-name
29631     0/imm32/no-rm32
29632     0/imm32/no-r32
29633     0/imm32/no-imm32
29634     0/imm32/no-imm8
29635     1/imm32/disp32-is-first-inout
29636     0/imm32/no-xm32
29637     0/imm32/no-x32
29638     0x11/imm32/alloc-id:fake
29639     _Primitive-loop-if-addr>=-named/imm32/next
29640 _Primitive-loop-if-addr>=-named:  # (payload primitive)
29641     0x11/imm32/alloc-id:fake:payload
29642     0x11/imm32/alloc-id:fake
29643     _string-loop-if-addr>=/imm32/name
29644     0x11/imm32/alloc-id:fake
29645     Single-lit-var/imm32/inouts
29646     0/imm32/no-outputs
29647     0/imm32/no-outputs
29648     0x11/imm32/alloc-id:fake
29649     _string_0f_83_jump_label/imm32/subx-name
29650     0/imm32/no-rm32
29651     0/imm32/no-r32
29652     0/imm32/no-imm32
29653     0/imm32/no-imm8
29654     1/imm32/disp32-is-first-inout
29655     0/imm32/no-xm32
29656     0/imm32/no-x32
29657     0x11/imm32/alloc-id:fake
29658     _Primitive-loop-if-=-named/imm32/next
29659 _Primitive-loop-if-=-named:  # (payload primitive)
29660     0x11/imm32/alloc-id:fake:payload
29661     0x11/imm32/alloc-id:fake
29662     _string-loop-if-=/imm32/name
29663     0x11/imm32/alloc-id:fake
29664     Single-lit-var/imm32/inouts
29665     0/imm32/no-outputs
29666     0/imm32/no-outputs
29667     0x11/imm32/alloc-id:fake
29668     _string_0f_84_jump_label/imm32/subx-name
29669     0/imm32/no-rm32
29670     0/imm32/no-r32
29671     0/imm32/no-imm32
29672     0/imm32/no-imm8
29673     1/imm32/disp32-is-first-inout
29674     0/imm32/no-xm32
29675     0/imm32/no-x32
29676     0x11/imm32/alloc-id:fake
29677     _Primitive-loop-if-!=-named/imm32/next
29678 _Primitive-loop-if-!=-named:  # (payload primitive)
29679     0x11/imm32/alloc-id:fake:payload
29680     0x11/imm32/alloc-id:fake
29681     _string-loop-if-!=/imm32/name
29682     0x11/imm32/alloc-id:fake
29683     Single-lit-var/imm32/inouts
29684     0/imm32/no-outputs
29685     0/imm32/no-outputs
29686     0x11/imm32/alloc-id:fake
29687     _string_0f_85_jump_label/imm32/subx-name
29688     0/imm32/no-rm32
29689     0/imm32/no-r32
29690     0/imm32/no-imm32
29691     0/imm32/no-imm8
29692     1/imm32/disp32-is-first-inout
29693     0/imm32/no-xm32
29694     0/imm32/no-x32
29695     0x11/imm32/alloc-id:fake
29696     _Primitive-loop-if-addr<=-named/imm32/next
29697 _Primitive-loop-if-addr<=-named:  # (payload primitive)
29698     0x11/imm32/alloc-id:fake:payload
29699     0x11/imm32/alloc-id:fake
29700     _string-loop-if-addr<=/imm32/name
29701     0x11/imm32/alloc-id:fake
29702     Single-lit-var/imm32/inouts
29703     0/imm32/no-outputs
29704     0/imm32/no-outputs
29705     0x11/imm32/alloc-id:fake
29706     _string_0f_86_jump_label/imm32/subx-name
29707     0/imm32/no-rm32
29708     0/imm32/no-r32
29709     0/imm32/no-imm32
29710     0/imm32/no-imm8
29711     1/imm32/disp32-is-first-inout
29712     0/imm32/no-xm32
29713     0/imm32/no-x32
29714     0x11/imm32/alloc-id:fake
29715     _Primitive-loop-if-addr>-named/imm32/next
29716 _Primitive-loop-if-addr>-named:  # (payload primitive)
29717     0x11/imm32/alloc-id:fake:payload
29718     0x11/imm32/alloc-id:fake
29719     _string-loop-if-addr>/imm32/name
29720     0x11/imm32/alloc-id:fake
29721     Single-lit-var/imm32/inouts
29722     0/imm32/no-outputs
29723     0/imm32/no-outputs
29724     0x11/imm32/alloc-id:fake
29725     _string_0f_87_jump_label/imm32/subx-name
29726     0/imm32/no-rm32
29727     0/imm32/no-r32
29728     0/imm32/no-imm32
29729     0/imm32/no-imm8
29730     1/imm32/disp32-is-first-inout
29731     0/imm32/no-xm32
29732     0/imm32/no-x32
29733     0x11/imm32/alloc-id:fake
29734     _Primitive-loop-if-<-named/imm32/next
29735 _Primitive-loop-if-<-named:  # (payload primitive)
29736     0x11/imm32/alloc-id:fake:payload
29737     0x11/imm32/alloc-id:fake
29738     _string-loop-if-</imm32/name
29739     0x11/imm32/alloc-id:fake
29740     Single-lit-var/imm32/inouts
29741     0/imm32/no-outputs
29742     0/imm32/no-outputs
29743     0x11/imm32/alloc-id:fake
29744     _string_0f_8c_jump_label/imm32/subx-name
29745     0/imm32/no-rm32
29746     0/imm32/no-r32
29747     0/imm32/no-imm32
29748     0/imm32/no-imm8
29749     1/imm32/disp32-is-first-inout
29750     0/imm32/no-xm32
29751     0/imm32/no-x32
29752     0x11/imm32/alloc-id:fake
29753     _Primitive-loop-if->=-named/imm32/next
29754 _Primitive-loop-if->=-named:  # (payload primitive)
29755     0x11/imm32/alloc-id:fake:payload
29756     0x11/imm32/alloc-id:fake
29757     _string-loop-if->=/imm32/name
29758     0x11/imm32/alloc-id:fake
29759     Single-lit-var/imm32/inouts
29760     0/imm32/no-outputs
29761     0/imm32/no-outputs
29762     0x11/imm32/alloc-id:fake
29763     _string_0f_8d_jump_label/imm32/subx-name
29764     0/imm32/no-rm32
29765     0/imm32/no-r32
29766     0/imm32/no-imm32
29767     0/imm32/no-imm8
29768     1/imm32/disp32-is-first-inout
29769     0/imm32/no-xm32
29770     0/imm32/no-x32
29771     0x11/imm32/alloc-id:fake
29772     _Primitive-loop-if-<=-named/imm32/next
29773 _Primitive-loop-if-<=-named:  # (payload primitive)
29774     0x11/imm32/alloc-id:fake:payload
29775     0x11/imm32/alloc-id:fake
29776     _string-loop-if-<=/imm32/name
29777     0x11/imm32/alloc-id:fake
29778     Single-lit-var/imm32/inouts
29779     0/imm32/no-outputs
29780     0/imm32/no-outputs
29781     0x11/imm32/alloc-id:fake
29782     _string_0f_8e_jump_label/imm32/subx-name
29783     0/imm32/no-rm32
29784     0/imm32/no-r32
29785     0/imm32/no-imm32
29786     0/imm32/no-imm8
29787     1/imm32/disp32-is-first-inout
29788     0/imm32/no-xm32
29789     0/imm32/no-x32
29790     0x11/imm32/alloc-id:fake
29791     _Primitive-loop-if->-named/imm32/next
29792 _Primitive-loop-if->-named:  # (payload primitive)
29793     0x11/imm32/alloc-id:fake:payload
29794     0x11/imm32/alloc-id:fake
29795     _string-loop-if->/imm32/name
29796     0x11/imm32/alloc-id:fake
29797     Single-lit-var/imm32/inouts
29798     0/imm32/no-outputs
29799     0/imm32/no-outputs
29800     0x11/imm32/alloc-id:fake
29801     _string_0f_8f_jump_label/imm32/subx-name
29802     0/imm32/no-rm32
29803     0/imm32/no-r32
29804     0/imm32/no-imm32
29805     0/imm32/no-imm8
29806     1/imm32/disp32-is-first-inout
29807     0/imm32/no-xm32
29808     0/imm32/no-x32
29809     0x11/imm32/alloc-id:fake
29810     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
29811 _Primitive-loop-named:  # (payload primitive)
29812     0x11/imm32/alloc-id:fake:payload
29813     0x11/imm32/alloc-id:fake
29814     _string-loop/imm32/name
29815     0x11/imm32/alloc-id:fake
29816     Single-lit-var/imm32/inouts
29817     0/imm32/no-outputs
29818     0/imm32/no-outputs
29819     0x11/imm32/alloc-id:fake
29820     _string_e9_jump_label/imm32/subx-name
29821     0/imm32/no-rm32
29822     0/imm32/no-r32
29823     0/imm32/no-imm32
29824     0/imm32/no-imm8
29825     1/imm32/disp32-is-first-inout
29826     0/imm32/no-xm32
29827     0/imm32/no-x32
29828     0x11/imm32/alloc-id:fake
29829     _Primitive-break-if-float</imm32/next
29830 # - branches based on floating-point comparisons
29831 _Primitive-break-if-float<:  # (payload primitive)
29832     0x11/imm32/alloc-id:fake:payload
29833     0x11/imm32/alloc-id:fake
29834     _string-break-if-float</imm32/name
29835     0/imm32/no-inouts
29836     0/imm32/no-inouts
29837     0/imm32/no-outputs
29838     0/imm32/no-outputs
29839     0x11/imm32/alloc-id:fake
29840     _string_0f_82_jump_break/imm32/subx-name
29841     0/imm32/no-rm32
29842     0/imm32/no-r32
29843     0/imm32/no-imm32
29844     0/imm32/no-imm8
29845     0/imm32/no-disp32
29846     0/imm32/no-xm32
29847     0/imm32/no-x32
29848     0x11/imm32/alloc-id:fake
29849     _Primitive-break-if-float>=/imm32/next
29850 _Primitive-break-if-float>=:  # (payload primitive)
29851     0x11/imm32/alloc-id:fake:payload
29852     0x11/imm32/alloc-id:fake
29853     _string-break-if-float>=/imm32/name
29854     0/imm32/no-inouts
29855     0/imm32/no-inouts
29856     0/imm32/no-outputs
29857     0/imm32/no-outputs
29858     0x11/imm32/alloc-id:fake
29859     _string_0f_83_jump_break/imm32/subx-name
29860     0/imm32/no-rm32
29861     0/imm32/no-r32
29862     0/imm32/no-imm32
29863     0/imm32/no-imm8
29864     0/imm32/no-disp32
29865     0/imm32/no-xm32
29866     0/imm32/no-x32
29867     0x11/imm32/alloc-id:fake
29868     _Primitive-break-if-float<=/imm32/next
29869 _Primitive-break-if-float<=:  # (payload primitive)
29870     0x11/imm32/alloc-id:fake:payload
29871     0x11/imm32/alloc-id:fake
29872     _string-break-if-float<=/imm32/name
29873     0/imm32/no-inouts
29874     0/imm32/no-inouts
29875     0/imm32/no-outputs
29876     0/imm32/no-outputs
29877     0x11/imm32/alloc-id:fake
29878     _string_0f_86_jump_break/imm32/subx-name
29879     0/imm32/no-rm32
29880     0/imm32/no-r32
29881     0/imm32/no-imm32
29882     0/imm32/no-imm8
29883     0/imm32/no-disp32
29884     0/imm32/no-xm32
29885     0/imm32/no-x32
29886     0x11/imm32/alloc-id:fake
29887     _Primitive-break-if-float>/imm32/next
29888 _Primitive-break-if-float>:  # (payload primitive)
29889     0x11/imm32/alloc-id:fake:payload
29890     0x11/imm32/alloc-id:fake
29891     _string-break-if-float>/imm32/name
29892     0/imm32/no-inouts
29893     0/imm32/no-inouts
29894     0/imm32/no-outputs
29895     0/imm32/no-outputs
29896     0x11/imm32/alloc-id:fake
29897     _string_0f_87_jump_break/imm32/subx-name
29898     0/imm32/no-rm32
29899     0/imm32/no-r32
29900     0/imm32/no-imm32
29901     0/imm32/no-imm8
29902     0/imm32/no-disp32
29903     0/imm32/no-xm32
29904     0/imm32/no-x32
29905     0x11/imm32/alloc-id:fake
29906     _Primitive-loop-if-float</imm32/next
29907 _Primitive-loop-if-float<:  # (payload primitive)
29908     0x11/imm32/alloc-id:fake:payload
29909     0x11/imm32/alloc-id:fake
29910     _string-loop-if-float</imm32/name
29911     0/imm32/no-inouts
29912     0/imm32/no-inouts
29913     0/imm32/no-outputs
29914     0/imm32/no-outputs
29915     0x11/imm32/alloc-id:fake
29916     _string_0f_82_jump_loop/imm32/subx-name
29917     0/imm32/no-rm32
29918     0/imm32/no-r32
29919     0/imm32/no-imm32
29920     0/imm32/no-imm8
29921     0/imm32/no-disp32
29922     0/imm32/no-xm32
29923     0/imm32/no-x32
29924     0x11/imm32/alloc-id:fake
29925     _Primitive-loop-if-float>=/imm32/next
29926 _Primitive-loop-if-float>=:  # (payload primitive)
29927     0x11/imm32/alloc-id:fake:payload
29928     0x11/imm32/alloc-id:fake
29929     _string-loop-if-float>=/imm32/name
29930     0/imm32/no-inouts
29931     0/imm32/no-inouts
29932     0/imm32/no-outputs
29933     0/imm32/no-outputs
29934     0x11/imm32/alloc-id:fake
29935     _string_0f_83_jump_loop/imm32/subx-name
29936     0/imm32/no-rm32
29937     0/imm32/no-r32
29938     0/imm32/no-imm32
29939     0/imm32/no-imm8
29940     0/imm32/no-disp32
29941     0/imm32/no-xm32
29942     0/imm32/no-x32
29943     0x11/imm32/alloc-id:fake
29944     _Primitive-loop-if-float<=/imm32/next
29945 _Primitive-loop-if-float<=:  # (payload primitive)
29946     0x11/imm32/alloc-id:fake:payload
29947     0x11/imm32/alloc-id:fake
29948     _string-loop-if-float<=/imm32/name
29949     0/imm32/no-inouts
29950     0/imm32/no-inouts
29951     0/imm32/no-outputs
29952     0/imm32/no-outputs
29953     0x11/imm32/alloc-id:fake
29954     _string_0f_86_jump_loop/imm32/subx-name
29955     0/imm32/no-rm32
29956     0/imm32/no-r32
29957     0/imm32/no-imm32
29958     0/imm32/no-imm8
29959     0/imm32/no-disp32
29960     0/imm32/no-xm32
29961     0/imm32/no-x32
29962     0x11/imm32/alloc-id:fake
29963     _Primitive-loop-if-float>/imm32/next
29964 _Primitive-loop-if-float>:  # (payload primitive)
29965     0x11/imm32/alloc-id:fake:payload
29966     0x11/imm32/alloc-id:fake
29967     _string-loop-if-float>/imm32/name
29968     0/imm32/no-inouts
29969     0/imm32/no-inouts
29970     0/imm32/no-outputs
29971     0/imm32/no-outputs
29972     0x11/imm32/alloc-id:fake
29973     _string_0f_87_jump_loop/imm32/subx-name
29974     0/imm32/no-rm32
29975     0/imm32/no-r32
29976     0/imm32/no-imm32
29977     0/imm32/no-imm8
29978     0/imm32/no-disp32
29979     0/imm32/no-xm32
29980     0/imm32/no-x32
29981     0x11/imm32/alloc-id:fake
29982     _Primitive-break-if-float<-named/imm32/next
29983 _Primitive-break-if-float<-named:  # (payload primitive)
29984     0x11/imm32/alloc-id:fake:payload
29985     0x11/imm32/alloc-id:fake
29986     _string-break-if-float</imm32/name
29987     0x11/imm32/alloc-id:fake
29988     Single-lit-var/imm32/inouts
29989     0/imm32/no-outputs
29990     0/imm32/no-outputs
29991     0x11/imm32/alloc-id:fake
29992     _string_0f_82_jump_label/imm32/subx-name
29993     0/imm32/no-rm32
29994     0/imm32/no-r32
29995     0/imm32/no-imm32
29996     0/imm32/no-imm8
29997     1/imm32/disp32-is-first-inout
29998     0/imm32/no-xm32
29999     0/imm32/no-x32
30000     0x11/imm32/alloc-id:fake
30001     _Primitive-break-if-float>=-named/imm32/next
30002 _Primitive-break-if-float>=-named:  # (payload primitive)
30003     0x11/imm32/alloc-id:fake:payload
30004     0x11/imm32/alloc-id:fake
30005     _string-break-if-float>=/imm32/name
30006     0x11/imm32/alloc-id:fake
30007     Single-lit-var/imm32/inouts
30008     0/imm32/no-outputs
30009     0/imm32/no-outputs
30010     0x11/imm32/alloc-id:fake
30011     _string_0f_83_jump_label/imm32/subx-name
30012     0/imm32/no-rm32
30013     0/imm32/no-r32
30014     0/imm32/no-imm32
30015     0/imm32/no-imm8
30016     1/imm32/disp32-is-first-inout
30017     0/imm32/no-xm32
30018     0/imm32/no-x32
30019     0x11/imm32/alloc-id:fake
30020     _Primitive-break-if-float<=-named/imm32/next
30021 _Primitive-break-if-float<=-named:  # (payload primitive)
30022     0x11/imm32/alloc-id:fake:payload
30023     0x11/imm32/alloc-id:fake
30024     _string-break-if-float<=/imm32/name
30025     0x11/imm32/alloc-id:fake
30026     Single-lit-var/imm32/inouts
30027     0/imm32/no-outputs
30028     0/imm32/no-outputs
30029     0x11/imm32/alloc-id:fake
30030     _string_0f_86_jump_label/imm32/subx-name
30031     0/imm32/no-rm32
30032     0/imm32/no-r32
30033     0/imm32/no-imm32
30034     0/imm32/no-imm8
30035     1/imm32/disp32-is-first-inout
30036     0/imm32/no-xm32
30037     0/imm32/no-x32
30038     0x11/imm32/alloc-id:fake
30039     _Primitive-break-if-float>-named/imm32/next
30040 _Primitive-break-if-float>-named:  # (payload primitive)
30041     0x11/imm32/alloc-id:fake:payload
30042     0x11/imm32/alloc-id:fake
30043     _string-break-if-float>/imm32/name
30044     0x11/imm32/alloc-id:fake
30045     Single-lit-var/imm32/inouts
30046     0/imm32/no-outputs
30047     0/imm32/no-outputs
30048     0x11/imm32/alloc-id:fake
30049     _string_0f_87_jump_label/imm32/subx-name
30050     0/imm32/no-rm32
30051     0/imm32/no-r32
30052     0/imm32/no-imm32
30053     0/imm32/no-imm8
30054     1/imm32/disp32-is-first-inout
30055     0/imm32/no-xm32
30056     0/imm32/no-x32
30057     0x11/imm32/alloc-id:fake
30058     _Primitive-loop-if-float<-named/imm32/next
30059 _Primitive-loop-if-float<-named:  # (payload primitive)
30060     0x11/imm32/alloc-id:fake:payload
30061     0x11/imm32/alloc-id:fake
30062     _string-loop-if-float</imm32/name
30063     0x11/imm32/alloc-id:fake
30064     Single-lit-var/imm32/inouts
30065     0/imm32/no-outputs
30066     0/imm32/no-outputs
30067     0x11/imm32/alloc-id:fake
30068     _string_0f_82_jump_label/imm32/subx-name
30069     0/imm32/no-rm32
30070     0/imm32/no-r32
30071     0/imm32/no-imm32
30072     0/imm32/no-imm8
30073     1/imm32/disp32-is-first-inout
30074     0/imm32/no-xm32
30075     0/imm32/no-x32
30076     0x11/imm32/alloc-id:fake
30077     _Primitive-loop-if-float>=-named/imm32/next
30078 _Primitive-loop-if-float>=-named:  # (payload primitive)
30079     0x11/imm32/alloc-id:fake:payload
30080     0x11/imm32/alloc-id:fake
30081     _string-loop-if-float>=/imm32/name
30082     0x11/imm32/alloc-id:fake
30083     Single-lit-var/imm32/inouts
30084     0/imm32/no-outputs
30085     0/imm32/no-outputs
30086     0x11/imm32/alloc-id:fake
30087     _string_0f_83_jump_label/imm32/subx-name
30088     0/imm32/no-rm32
30089     0/imm32/no-r32
30090     0/imm32/no-imm32
30091     0/imm32/no-imm8
30092     1/imm32/disp32-is-first-inout
30093     0/imm32/no-xm32
30094     0/imm32/no-x32
30095     0x11/imm32/alloc-id:fake
30096     _Primitive-loop-if-float<=-named/imm32/next
30097 _Primitive-loop-if-float<=-named:  # (payload primitive)
30098     0x11/imm32/alloc-id:fake:payload
30099     0x11/imm32/alloc-id:fake
30100     _string-loop-if-float<=/imm32/name
30101     0x11/imm32/alloc-id:fake
30102     Single-lit-var/imm32/inouts
30103     0/imm32/no-outputs
30104     0/imm32/no-outputs
30105     0x11/imm32/alloc-id:fake
30106     _string_0f_86_jump_label/imm32/subx-name
30107     0/imm32/no-rm32
30108     0/imm32/no-r32
30109     0/imm32/no-imm32
30110     0/imm32/no-imm8
30111     1/imm32/disp32-is-first-inout
30112     0/imm32/no-xm32
30113     0/imm32/no-x32
30114     0x11/imm32/alloc-id:fake
30115     _Primitive-loop-if-float>-named/imm32/next
30116 _Primitive-loop-if-float>-named:  # (payload primitive)
30117     0x11/imm32/alloc-id:fake:payload
30118     0x11/imm32/alloc-id:fake
30119     _string-loop-if-float>/imm32/name
30120     0x11/imm32/alloc-id:fake
30121     Single-lit-var/imm32/inouts
30122     0/imm32/no-outputs
30123     0/imm32/no-outputs
30124     0x11/imm32/alloc-id:fake
30125     _string_0f_87_jump_label/imm32/subx-name
30126     0/imm32/no-rm32
30127     0/imm32/no-r32
30128     0/imm32/no-imm32
30129     0/imm32/no-imm8
30130     1/imm32/disp32-is-first-inout
30131     0/imm32/no-xm32
30132     0/imm32/no-x32
30133     0/imm32/next
30134     0/imm32/next
30135 
30136 # string literals for Mu instructions
30137 _string-add:  # (payload array byte)
30138     0x11/imm32/alloc-id:fake:payload
30139     # "add"
30140     0x3/imm32/size
30141     0x61/a 0x64/d 0x64/d
30142 _string-address:  # (payload array byte)
30143     0x11/imm32/alloc-id:fake:payload
30144     # "address"
30145     0x7/imm32/size
30146     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
30147 _string-add-to:  # (payload array byte)
30148     0x11/imm32/alloc-id:fake:payload
30149     # "add-to"
30150     0x6/imm32/size
30151     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
30152 _string-and:  # (payload array byte)
30153     0x11/imm32/alloc-id:fake:payload
30154     # "and"
30155     0x3/imm32/size
30156     0x61/a 0x6e/n 0x64/d
30157 _string-and-with:  # (payload array byte)
30158     0x11/imm32/alloc-id:fake:payload
30159     # "and-with"
30160     0x8/imm32/size
30161     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30162 _string-break:  # (payload array byte)
30163     0x11/imm32/alloc-id:fake:payload
30164     # "break"
30165     0x5/imm32/size
30166     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
30167 _string-break-if-<:  # (payload array byte)
30168     0x11/imm32/alloc-id:fake:payload
30169     # "break-if-<"
30170     0xa/imm32/size
30171     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
30172 _string-break-if-<=:  # (payload array byte)
30173     0x11/imm32/alloc-id:fake:payload
30174     # "break-if-<="
30175     0xb/imm32/size
30176     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
30177 _string-break-if-=:  # (payload array byte)
30178     0x11/imm32/alloc-id:fake:payload
30179     # "break-if-="
30180     0xa/imm32/size
30181     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
30182 _string-break-if->:  # (payload array byte)
30183     0x11/imm32/alloc-id:fake:payload
30184     # "break-if->"
30185     0xa/imm32/size
30186     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
30187 _string-break-if->=:  # (payload array byte)
30188     0x11/imm32/alloc-id:fake:payload
30189     # "break-if->="
30190     0xb/imm32/size
30191     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
30192 _string-break-if-!=:  # (payload array byte)
30193     0x11/imm32/alloc-id:fake:payload
30194     # "break-if-!="
30195     0xb/imm32/size
30196     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
30197 _string-break-if-addr<:  # (payload array byte)
30198     0x11/imm32/alloc-id:fake:payload
30199     # "break-if-addr<"
30200     0xe/imm32/size
30201     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/<
30202 _string-break-if-addr<=:  # (payload array byte)
30203     0x11/imm32/alloc-id:fake:payload
30204     # "break-if-addr<="
30205     0xf/imm32/size
30206     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/=
30207 _string-break-if-addr>:  # (payload array byte)
30208     0x11/imm32/alloc-id:fake:payload
30209     # "break-if-addr>"
30210     0xe/imm32/size
30211     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/>
30212 _string-break-if-addr>=:  # (payload array byte)
30213     0x11/imm32/alloc-id:fake:payload
30214     # "break-if-addr>="
30215     0xf/imm32/size
30216     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/=
30217 _string-break-if-float<:  # (payload array byte)
30218     0x11/imm32/alloc-id:fake:payload
30219     # "break-if-float<"
30220     0xf/imm32/size
30221     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/<
30222 _string-break-if-float<=:  # (payload array byte)
30223     0x11/imm32/alloc-id:fake:payload
30224     # "break-if-float<="
30225     0x10/imm32/size
30226     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/=
30227 _string-break-if-float>:  # (payload array byte)
30228     0x11/imm32/alloc-id:fake:payload
30229     # "break-if-float>"
30230     0xf/imm32/size
30231     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/>
30232 _string-break-if-float>=:  # (payload array byte)
30233     0x11/imm32/alloc-id:fake:payload
30234     # "break-if-float>="
30235     0x10/imm32/size
30236     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/=
30237 _string-compare:  # (payload array byte)
30238     0x11/imm32/alloc-id:fake:payload
30239     # "compare"
30240     0x7/imm32/size
30241     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
30242 _string-copy:  # (payload array byte)
30243     0x11/imm32/alloc-id:fake:payload
30244     # "copy"
30245     0x4/imm32/size
30246     0x63/c 0x6f/o 0x70/p 0x79/y
30247 _string-copy-to:  # (payload array byte)
30248     0x11/imm32/alloc-id:fake:payload
30249     # "copy-to"
30250     0x7/imm32/size
30251     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
30252 _string-copy-byte:
30253     0x11/imm32/alloc-id:fake:payload
30254     # "copy-byte"
30255     0x9/imm32/size
30256     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
30257 _string-copy-byte-to:
30258     0x11/imm32/alloc-id:fake:payload
30259     # "copy-byte-to"
30260     0xc/imm32/size
30261     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
30262 _string-decrement:  # (payload array byte)
30263     0x11/imm32/alloc-id:fake:payload
30264     # "decrement"
30265     0x9/imm32/size
30266     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
30267 _string-increment:  # (payload array byte)
30268     0x11/imm32/alloc-id:fake:payload
30269     # "increment"
30270     0x9/imm32/size
30271     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
30272 _string-loop:  # (payload array byte)
30273     0x11/imm32/alloc-id:fake:payload
30274     # "loop"
30275     0x4/imm32/size
30276     0x6c/l 0x6f/o 0x6f/o 0x70/p
30277 _string-loop-if-<:  # (payload array byte)
30278     0x11/imm32/alloc-id:fake:payload
30279     # "loop-if-<"
30280     0x9/imm32/size
30281     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
30282 _string-loop-if-<=:  # (payload array byte)
30283     0x11/imm32/alloc-id:fake:payload
30284     # "loop-if-<="
30285     0xa/imm32/size
30286     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
30287 _string-loop-if-=:  # (payload array byte)
30288     0x11/imm32/alloc-id:fake:payload
30289     # "loop-if-="
30290     0x9/imm32/size
30291     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
30292 _string-loop-if->:  # (payload array byte)
30293     0x11/imm32/alloc-id:fake:payload
30294     # "loop-if->"
30295     0x9/imm32/size
30296     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
30297 _string-loop-if->=:  # (payload array byte)
30298     0x11/imm32/alloc-id:fake:payload
30299     # "loop-if->="
30300     0xa/imm32/size
30301     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
30302 _string-loop-if-!=:  # (payload array byte)
30303     0x11/imm32/alloc-id:fake:payload
30304     # "loop-if-!="
30305     0xa/imm32/size
30306     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
30307 _string-loop-if-addr<:  # (payload array byte)
30308     0x11/imm32/alloc-id:fake:payload
30309     # "loop-if-addr<"
30310     0xd/imm32/size
30311     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/<
30312 _string-loop-if-addr<=:  # (payload array byte)
30313     0x11/imm32/alloc-id:fake:payload
30314     # "loop-if-addr<="
30315     0xe/imm32/size
30316     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/=
30317 _string-loop-if-addr>:  # (payload array byte)
30318     0x11/imm32/alloc-id:fake:payload
30319     # "loop-if-addr>"
30320     0xd/imm32/size
30321     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/>
30322 _string-loop-if-addr>=:  # (payload array byte)
30323     0x11/imm32/alloc-id:fake:payload
30324     # "loop-if-addr>="
30325     0xe/imm32/size
30326     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/=
30327 _string-loop-if-float<:  # (payload array byte)
30328     0x11/imm32/alloc-id:fake:payload
30329     # "loop-if-float<"
30330     0xe/imm32/size
30331     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/<
30332 _string-loop-if-float<=:  # (payload array byte)
30333     0x11/imm32/alloc-id:fake:payload
30334     # "loop-if-float<="
30335     0xf/imm32/size
30336     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/=
30337 _string-loop-if-float>:  # (payload array byte)
30338     0x11/imm32/alloc-id:fake:payload
30339     # "loop-if-float>"
30340     0xe/imm32/size
30341     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/>
30342 _string-loop-if-float>=:  # (payload array byte)
30343     0x11/imm32/alloc-id:fake:payload
30344     # "loop-if-float>="
30345     0xf/imm32/size
30346     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/=
30347 _string-multiply:  # (payload array byte)
30348     0x11/imm32/alloc-id:fake:payload
30349     # "multiply"
30350     0x8/imm32/size
30351     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
30352 _string-convert:  # (payload array byte)
30353     0x11/imm32/alloc-id:fake:payload
30354     # "convert"
30355     0x7/imm32/size
30356     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
30357 _string-truncate:  # (payload array byte)
30358     0x11/imm32/alloc-id:fake:payload
30359     # "truncate"
30360     0x8/imm32/size
30361     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
30362 _string-reinterpret:  # (payload array byte)
30363     0x11/imm32/alloc-id:fake:payload
30364     # "reinterpret"
30365     0xb/imm32/size
30366     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
30367 _string-divide:
30368     0x11/imm32/alloc-id:fake:payload
30369     # "divide"
30370     0x6/imm32/size
30371     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
30372 _string-max:
30373     0x11/imm32/alloc-id:fake:payload
30374     # "max"
30375     0x3/imm32/size
30376     0x6d/m 0x61/a 0x78/x
30377 _string-min:
30378     0x11/imm32/alloc-id:fake:payload
30379     # "min"
30380     0x3/imm32/size
30381     0x6d/m 0x69/i 0x6e/n
30382 _string-reciprocal:
30383     0x11/imm32/alloc-id:fake:payload
30384     # "reciprocal"
30385     0xa/imm32/size
30386     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
30387 _string-square-root:
30388     0x11/imm32/alloc-id:fake:payload
30389     # "square-root"
30390     0xb/imm32/size
30391     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
30392 _string-inverse-square-root:
30393     0x11/imm32/alloc-id:fake:payload
30394     # "inverse-square-root"
30395     0x13/imm32/size
30396     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
30397 _string-negate:  # (payload array byte)
30398     0x11/imm32/alloc-id:fake:payload
30399     # "negate"
30400     0x6/imm32/size
30401     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
30402 _string-or:  # (payload array byte)
30403     0x11/imm32/alloc-id:fake:payload
30404     # "or"
30405     0x2/imm32/size
30406     0x6f/o 0x72/r
30407 _string-or-with:  # (payload array byte)
30408     0x11/imm32/alloc-id:fake:payload
30409     # "or-with"
30410     0x7/imm32/size
30411     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30412 _string-subtract:  # (payload array byte)
30413     0x11/imm32/alloc-id:fake:payload
30414     # "subtract"
30415     0x8/imm32/size
30416     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
30417 _string-subtract-from:  # (payload array byte)
30418     0x11/imm32/alloc-id:fake:payload
30419     # "subtract-from"
30420     0xd/imm32/size
30421     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
30422 _string-xor:  # (payload array byte)
30423     0x11/imm32/alloc-id:fake:payload
30424     # "xor"
30425     0x3/imm32/size
30426     0x78/x 0x6f/o 0x72/r
30427 _string-xor-with:  # (payload array byte)
30428     0x11/imm32/alloc-id:fake:payload
30429     # "xor-with"
30430     0x8/imm32/size
30431     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30432 _string-shift-left:  # (payload array byte)
30433     0x11/imm32/alloc-id:fake:payload
30434     # "shift-left"
30435     0xa/imm32/size
30436     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
30437 _string-shift-right:  # (payload array byte)
30438     0x11/imm32/alloc-id:fake:payload
30439     # "shift-right"
30440     0xb/imm32/size
30441     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
30442 _string-shift-right-signed:  # (payload array byte)
30443     0x11/imm32/alloc-id:fake:payload
30444     # "shift-right-signed"
30445     0x12/imm32/size
30446     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
30447 
30448 # string literals for SubX instructions
30449 _string_01_add_to:  # (payload array byte)
30450     0x11/imm32/alloc-id:fake:payload
30451     # "01/add-to"
30452     0x9/imm32/size
30453     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
30454 _string_03_add:  # (payload array byte)
30455     0x11/imm32/alloc-id:fake:payload
30456     # "03/add"
30457     0x6/imm32/size
30458     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
30459 _string_05_add_to_eax:  # (payload array byte)
30460     0x11/imm32/alloc-id:fake:payload
30461     # "05/add-to-eax"
30462     0xd/imm32/size
30463     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
30464 _string_09_or_with:  # (payload array byte)
30465     0x11/imm32/alloc-id:fake:payload
30466     # "09/or-with"
30467     0xa/imm32/size
30468     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30469 _string_0b_or:  # (payload array byte)
30470     0x11/imm32/alloc-id:fake:payload
30471     # "0b/or"
30472     0x5/imm32/size
30473     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
30474 _string_0d_or_with_eax:  # (payload array byte)
30475     0x11/imm32/alloc-id:fake:payload
30476     # "0d/or-with-eax"
30477     0xe/imm32/size
30478     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
30479 _string_0f_82_jump_label:  # (payload array byte)
30480     0x11/imm32/alloc-id:fake:payload
30481     # "0f 82/jump-if-addr<"
30482     0x13/imm32/size
30483     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/<
30484 _string_0f_82_jump_break:  # (payload array byte)
30485     0x11/imm32/alloc-id:fake:payload
30486     # "0f 82/jump-if-addr< break/disp32"
30487     0x20/imm32/size
30488     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
30489 _string_0f_82_jump_loop:  # (payload array byte)
30490     0x11/imm32/alloc-id:fake:payload
30491     # "0f 82/jump-if-addr< loop/disp32"
30492     0x1f/imm32/size
30493     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
30494 _string_0f_83_jump_label:  # (payload array byte)
30495     0x11/imm32/alloc-id:fake:payload
30496     # "0f 83/jump-if-addr>="
30497     0x14/imm32/size
30498     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/=
30499 _string_0f_83_jump_break:  # (payload array byte)
30500     0x11/imm32/alloc-id:fake:payload
30501     # "0f 83/jump-if-addr>= break/disp32"
30502     0x21/imm32/size
30503     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
30504 _string_0f_83_jump_loop:  # (payload array byte)
30505     0x11/imm32/alloc-id:fake:payload
30506     # "0f 83/jump-if-addr>= loop/disp32"
30507     0x20/imm32/size
30508     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
30509 _string_0f_84_jump_label:  # (payload array byte)
30510     0x11/imm32/alloc-id:fake:payload
30511     # "0f 84/jump-if-="
30512     0xf/imm32/size
30513     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/=
30514 _string_0f_84_jump_break:  # (payload array byte)
30515     0x11/imm32/alloc-id:fake:payload
30516     # "0f 84/jump-if-= break/disp32"
30517     0x1c/imm32/size
30518     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
30519 _string_0f_84_jump_loop:  # (payload array byte)
30520     0x11/imm32/alloc-id:fake:payload
30521     # "0f 84/jump-if-= loop/disp32"
30522     0x1b/imm32/size
30523     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
30524 _string_0f_85_jump_label:  # (payload array byte)
30525     0x11/imm32/alloc-id:fake:payload
30526     # "0f 85/jump-if-!="
30527     0x10/imm32/size
30528     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/=
30529 _string_0f_85_jump_break:  # (payload array byte)
30530     0x11/imm32/alloc-id:fake:payload
30531     # "0f 85/jump-if-!= break/disp32"
30532     0x1d/imm32/size
30533     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
30534 _string_0f_85_jump_loop:  # (payload array byte)
30535     0x11/imm32/alloc-id:fake:payload
30536     # "0f 85/jump-if-!= loop/disp32"
30537     0x1c/imm32/size
30538     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
30539 _string_0f_86_jump_label:  # (payload array byte)
30540     0x11/imm32/alloc-id:fake:payload
30541     # "0f 86/jump-if-addr<="
30542     0x14/imm32/size
30543     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/=
30544 _string_0f_86_jump_break:  # (payload array byte)
30545     0x11/imm32/alloc-id:fake:payload
30546     # "0f 86/jump-if-addr<= break/disp32"
30547     0x21/imm32/size
30548     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
30549 _string_0f_86_jump_loop:  # (payload array byte)
30550     0x11/imm32/alloc-id:fake:payload
30551     # "0f 86/jump-if-addr<= loop/disp32"
30552     0x20/imm32/size
30553     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
30554 _string_0f_87_jump_label:  # (payload array byte)
30555     0x11/imm32/alloc-id:fake:payload
30556     # "0f 87/jump-if-addr>"
30557     0x13/imm32/size
30558     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/>
30559 _string_0f_87_jump_break:  # (payload array byte)
30560     0x11/imm32/alloc-id:fake:payload
30561     # "0f 87/jump-if-addr> break/disp32"
30562     0x20/imm32/size
30563     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
30564 _string_0f_87_jump_loop:  # (payload array byte)
30565     0x11/imm32/alloc-id:fake:payload
30566     # "0f 87/jump-if-addr> loop/disp32"
30567     0x1f/imm32/size
30568     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
30569 _string_0f_8c_jump_label:  # (payload array byte)
30570     0x11/imm32/alloc-id:fake:payload
30571     # "0f 8c/jump-if-<"
30572     0xf/imm32/size
30573     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/<
30574 _string_0f_8c_jump_break:  # (payload array byte)
30575     0x11/imm32/alloc-id:fake:payload
30576     # "0f 8c/jump-if-< break/disp32"
30577     0x1c/imm32/size
30578     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
30579 _string_0f_8c_jump_loop:  # (payload array byte)
30580     0x11/imm32/alloc-id:fake:payload
30581     # "0f 8c/jump-if-< loop/disp32"
30582     0x1b/imm32/size
30583     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
30584 _string_0f_8d_jump_label:  # (payload array byte)
30585     0x11/imm32/alloc-id:fake:payload
30586     # "0f 8d/jump-if->="
30587     0x10/imm32/size
30588     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/=
30589 _string_0f_8d_jump_break:  # (payload array byte)
30590     0x11/imm32/alloc-id:fake:payload
30591     # "0f 8d/jump-if->= break/disp32"
30592     0x1d/imm32/size
30593     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
30594 _string_0f_8d_jump_loop:  # (payload array byte)
30595     0x11/imm32/alloc-id:fake:payload
30596     # "0f 8d/jump-if->= loop/disp32"
30597     0x1c/imm32/size
30598     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
30599 _string_0f_8e_jump_label:  # (payload array byte)
30600     0x11/imm32/alloc-id:fake:payload
30601     # "0f 8e/jump-if-<="
30602     0x10/imm32/size
30603     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/=
30604 _string_0f_8e_jump_break:  # (payload array byte)
30605     0x11/imm32/alloc-id:fake:payload
30606     # "0f 8e/jump-if-<= break/disp32"
30607     0x1d/imm32/size
30608     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
30609 _string_0f_8e_jump_loop:  # (payload array byte)
30610     0x11/imm32/alloc-id:fake:payload
30611     # "0f 8e/jump-if-<= loop/disp32"
30612     0x1c/imm32/size
30613     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
30614 _string_0f_8f_jump_label:  # (payload array byte)
30615     0x11/imm32/alloc-id:fake:payload
30616     # "0f 8f/jump-if->"
30617     0xf/imm32/size
30618     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/>
30619 _string_0f_8f_jump_break:  # (payload array byte)
30620     0x11/imm32/alloc-id:fake:payload
30621     # "0f 8f/jump-if-> break/disp32"
30622     0x1c/imm32/size
30623     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
30624 _string_0f_8f_jump_loop:  # (payload array byte)
30625     0x11/imm32/alloc-id:fake:payload
30626     # "0f 8f/jump-if-> loop/disp32"
30627     0x1b/imm32/size
30628     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
30629 _string_0f_af_multiply:  # (payload array byte)
30630     0x11/imm32/alloc-id:fake:payload
30631     # "0f af/multiply"
30632     0xe/imm32/size
30633     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
30634 _string_f3_0f_2a_convert_to_float:
30635     0x11/imm32/alloc-id:fake:payload
30636     # "f3 0f 2a/convert-to-float"
30637     0x19/imm32/size
30638     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
30639 _string_f3_0f_2d_convert_to_int:
30640     0x11/imm32/alloc-id:fake:payload
30641     # "f3 0f 2d/convert-to-int"
30642     0x17/imm32/size
30643     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
30644 _string_f3_0f_2c_truncate_to_int:
30645     0x11/imm32/alloc-id:fake:payload
30646     # "f3 0f 2c/truncate-to-int"
30647     0x18/imm32/size
30648     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
30649 _string_f3_0f_58_add:
30650     0x11/imm32/alloc-id:fake:payload
30651     # "f3 0f 58/add"
30652     0xc/imm32/size
30653     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
30654 _string_f3_0f_5c_subtract:
30655     0x11/imm32/alloc-id:fake:payload
30656     # "f3 0f 5c/subtract"
30657     0x11/imm32/size
30658     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
30659 _string_f3_0f_59_multiply:
30660     0x11/imm32/alloc-id:fake:payload
30661     # "f3 0f 59/multiply"
30662     0x11/imm32/size
30663     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
30664 _string_f3_0f_5e_divide:
30665     0x11/imm32/alloc-id:fake:payload
30666     # "f3 0f 5e/divide"
30667     0xf/imm32/size
30668     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
30669 _string_f3_0f_53_reciprocal:
30670     0x11/imm32/alloc-id:fake:payload
30671     # "f3 0f 53/reciprocal"
30672     0x13/imm32/size
30673     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
30674 _string_f3_0f_51_square_root:
30675     0x11/imm32/alloc-id:fake:payload
30676     # "f3 0f 51/square-root"
30677     0x14/imm32/size
30678     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
30679 _string_f3_0f_52_inverse_square_root:
30680     0x11/imm32/alloc-id:fake:payload
30681     # "f3 0f 52/inverse-square-root"
30682     0x1c/imm32/size
30683     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
30684 _string_f3_0f_5d_min:
30685     0x11/imm32/alloc-id:fake:payload
30686     # "f3 0f 5d/min"
30687     0xc/imm32/size
30688     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
30689 _string_f3_0f_5f_max:
30690     0x11/imm32/alloc-id:fake:payload
30691     # "f3 0f 5f/max"
30692     0xc/imm32/size
30693     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
30694 _string_f3_0f_10_copy:
30695     0x11/imm32/alloc-id:fake:payload
30696     # "f3 0f 10/copy"
30697     0xd/imm32/size
30698     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
30699 _string_f3_0f_11_copy:
30700     0x11/imm32/alloc-id:fake:payload
30701     # "f3 0f 11/copy"
30702     0xd/imm32/size
30703     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
30704 _string_0f_2f_compare:
30705     0x11/imm32/alloc-id:fake:payload
30706     # "0f 2f/compare"
30707     0xd/imm32/size
30708     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
30709 _string_21_and_with:  # (payload array byte)
30710     0x11/imm32/alloc-id:fake:payload
30711     # "21/and-with"
30712     0xb/imm32/size
30713     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30714 _string_23_and:  # (payload array byte)
30715     0x11/imm32/alloc-id:fake:payload
30716     # "23/and"
30717     0x6/imm32/size
30718     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
30719 _string_25_and_with_eax:  # (payload array byte)
30720     0x11/imm32/alloc-id:fake:payload
30721     # "25/and-with-eax"
30722     0xf/imm32/size
30723     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
30724 _string_29_subtract_from:  # (payload array byte)
30725     0x11/imm32/alloc-id:fake:payload
30726     # "29/subtract-from"
30727     0x10/imm32/size
30728     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
30729 _string_2b_subtract:  # (payload array byte)
30730     0x11/imm32/alloc-id:fake:payload
30731     # "2b/subtract"
30732     0xb/imm32/size
30733     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
30734 _string_2d_subtract_from_eax:  # (payload array byte)
30735     0x11/imm32/alloc-id:fake:payload
30736     # "2d/subtract-from-eax"
30737     0x14/imm32/size
30738     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
30739 _string_31_xor_with:  # (payload array byte)
30740     0x11/imm32/alloc-id:fake:payload
30741     # "31/xor-with"
30742     0xb/imm32/size
30743     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
30744 _string_33_xor:  # (payload array byte)
30745     0x11/imm32/alloc-id:fake:payload
30746     # "33/xor"
30747     0x6/imm32/size
30748     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
30749 _string_35_xor_with_eax:  # (payload array byte)
30750     0x11/imm32/alloc-id:fake:payload
30751     # "35/xor-with-eax"
30752     0xf/imm32/size
30753     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
30754 _string_39_compare->:  # (payload array byte)
30755     0x11/imm32/alloc-id:fake:payload
30756     # "39/compare->"
30757     0xc/imm32/size
30758     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
30759 _string_3b_compare<-:  # (payload array byte)
30760     0x11/imm32/alloc-id:fake:payload
30761     # "3b/compare<-"
30762     0xc/imm32/size
30763     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
30764 _string_3d_compare_eax_with:  # (payload array byte)
30765     0x11/imm32/alloc-id:fake:payload
30766     # "3d/compare-eax-with"
30767     0x13/imm32/size
30768     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
30769 _string_40_increment_eax:  # (payload array byte)
30770     0x11/imm32/alloc-id:fake:payload
30771     # "40/increment-eax"
30772     0x10/imm32/size
30773     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
30774 _string_41_increment_ecx:  # (payload array byte)
30775     0x11/imm32/alloc-id:fake:payload
30776     # "41/increment-ecx"
30777     0x10/imm32/size
30778     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
30779 _string_42_increment_edx:  # (payload array byte)
30780     0x11/imm32/alloc-id:fake:payload
30781     # "42/increment-edx"
30782     0x10/imm32/size
30783     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
30784 _string_43_increment_ebx:  # (payload array byte)
30785     0x11/imm32/alloc-id:fake:payload
30786     # "43/increment-ebx"
30787     0x10/imm32/size
30788     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
30789 _string_46_increment_esi:  # (payload array byte)
30790     0x11/imm32/alloc-id:fake:payload
30791     # "46/increment-esi"
30792     0x10/imm32/size
30793     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
30794 _string_47_increment_edi:  # (payload array byte)
30795     0x11/imm32/alloc-id:fake:payload
30796     # "47/increment-edi"
30797     0x10/imm32/size
30798     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
30799 _string_48_decrement_eax:  # (payload array byte)
30800     0x11/imm32/alloc-id:fake:payload
30801     # "48/decrement-eax"
30802     0x10/imm32/size
30803     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
30804 _string_49_decrement_ecx:  # (payload array byte)
30805     0x11/imm32/alloc-id:fake:payload
30806     # "49/decrement-ecx"
30807     0x10/imm32/size
30808     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
30809 _string_4a_decrement_edx:  # (payload array byte)
30810     0x11/imm32/alloc-id:fake:payload
30811     # "4a/decrement-edx"
30812     0x10/imm32/size
30813     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
30814 _string_4b_decrement_ebx:  # (payload array byte)
30815     0x11/imm32/alloc-id:fake:payload
30816     # "4b/decrement-ebx"
30817     0x10/imm32/size
30818     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
30819 _string_4e_decrement_esi:  # (payload array byte)
30820     0x11/imm32/alloc-id:fake:payload
30821     # "4e/decrement-esi"
30822     0x10/imm32/size
30823     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
30824 _string_4f_decrement_edi:  # (payload array byte)
30825     0x11/imm32/alloc-id:fake:payload
30826     # "4f/decrement-edi"
30827     0x10/imm32/size
30828     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
30829 _string_81_subop_add:  # (payload array byte)
30830     0x11/imm32/alloc-id:fake:payload
30831     # "81 0/subop/add"
30832     0xe/imm32/size
30833     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
30834 _string_81_subop_or:  # (payload array byte)
30835     0x11/imm32/alloc-id:fake:payload
30836     # "81 1/subop/or"
30837     0xd/imm32/size
30838     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
30839 _string_81_subop_and:  # (payload array byte)
30840     0x11/imm32/alloc-id:fake:payload
30841     # "81 4/subop/and"
30842     0xe/imm32/size
30843     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
30844 _string_81_subop_subtract:  # (payload array byte)
30845     0x11/imm32/alloc-id:fake:payload
30846     # "81 5/subop/subtract"
30847     0x13/imm32/size
30848     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
30849 _string_81_subop_xor:  # (payload array byte)
30850     0x11/imm32/alloc-id:fake:payload
30851     # "81 6/subop/xor"
30852     0xe/imm32/size
30853     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
30854 _string_81_subop_compare:  # (payload array byte)
30855     0x11/imm32/alloc-id:fake:payload
30856     # "81 7/subop/compare"
30857     0x12/imm32/size
30858     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
30859 _string_89_<-:  # (payload array byte)
30860     0x11/imm32/alloc-id:fake:payload
30861     # "89/<-"
30862     0x5/imm32/size
30863     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
30864 _string_8b_->:  # (payload array byte)
30865     0x11/imm32/alloc-id:fake:payload
30866     # "8b/->"
30867     0x5/imm32/size
30868     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
30869 _string_8a_copy_byte:
30870     0x11/imm32/alloc-id:fake:payload
30871     # "8a/byte->"
30872     0x9/imm32/size
30873     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
30874 _string_88_copy_byte:
30875     0x11/imm32/alloc-id:fake:payload
30876     # "88/byte<-"
30877     0x9/imm32/size
30878     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
30879 _string_8d_copy_address:  # (payload array byte)
30880     0x11/imm32/alloc-id:fake:payload
30881     # "8d/copy-address"
30882     0xf/imm32/size
30883     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
30884 _string_b8_copy_to_eax:  # (payload array byte)
30885     0x11/imm32/alloc-id:fake:payload
30886     # "b8/copy-to-eax"
30887     0xe/imm32/size
30888     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
30889 _string_b9_copy_to_ecx:  # (payload array byte)
30890     0x11/imm32/alloc-id:fake:payload
30891     # "b9/copy-to-ecx"
30892     0xe/imm32/size
30893     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
30894 _string_ba_copy_to_edx:  # (payload array byte)
30895     0x11/imm32/alloc-id:fake:payload
30896     # "ba/copy-to-edx"
30897     0xe/imm32/size
30898     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
30899 _string_bb_copy_to_ebx:  # (payload array byte)
30900     0x11/imm32/alloc-id:fake:payload
30901     # "bb/copy-to-ebx"
30902     0xe/imm32/size
30903     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
30904 _string_be_copy_to_esi:  # (payload array byte)
30905     0x11/imm32/alloc-id:fake:payload
30906     # "be/copy-to-esi"
30907     0xe/imm32/size
30908     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
30909 _string_bf_copy_to_edi:  # (payload array byte)
30910     0x11/imm32/alloc-id:fake:payload
30911     # "bf/copy-to-edi"
30912     0xe/imm32/size
30913     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
30914 _string_c7_subop_copy:  # (payload array byte)
30915     0x11/imm32/alloc-id:fake:payload
30916     # "c7 0/subop/copy"
30917     0xf/imm32/size
30918     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
30919 _string_e9_jump_label:  # (payload array byte)
30920     0x11/imm32/alloc-id:fake:payload
30921     # "e9/jump"
30922     0x7/imm32/size
30923     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
30924 _string_e9_jump_break:  # (payload array byte)
30925     0x11/imm32/alloc-id:fake:payload
30926     # "e9/jump break/disp32"
30927     0x14/imm32/size
30928     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
30929 _string_e9_jump_loop:  # (payload array byte)
30930     0x11/imm32/alloc-id:fake:payload
30931     # "e9/jump loop/disp32"
30932     0x13/imm32/size
30933     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
30934 _string_f7_subop_negate:
30935     0x11/imm32/alloc-id:fake:payload
30936     # "f7 3/subop/negate"
30937     0x11/imm32/size
30938     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
30939 _string_ff_subop_increment:  # (payload array byte)
30940     0x11/imm32/alloc-id:fake:payload
30941     # "ff 0/subop/increment"
30942     0x14/imm32/size
30943     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
30944 _string_ff_subop_decrement:  # (payload array byte)
30945     0x11/imm32/alloc-id:fake:payload
30946     # "ff 1/subop/decrement"
30947     0x14/imm32/size
30948     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
30949 _string_c1_subop_shift_left:  # (payload array byte)
30950     0x11/imm32/alloc-id:fake:payload
30951     # "c1/shift 4/subop/left"
30952     0x15/imm32/size
30953     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
30954 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
30955     0x11/imm32/alloc-id:fake:payload
30956     # "c1/shift 5/subop/right-padding-zeroes"
30957     0x25/imm32/size
30958     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
30959 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
30960     0x11/imm32/alloc-id:fake:payload
30961     # "c1/shift 7/subop/right-preserving-sign"
30962     0x26/imm32/size
30963     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
30964 
30965 Single-int-var-in-mem:  # (payload list var)
30966     0x11/imm32/alloc-id:fake:payload
30967     0x11/imm32/alloc-id:fake
30968     Int-var-in-mem/imm32
30969     0/imm32/next
30970     0/imm32/next
30971 
30972 Int-var-in-mem:  # (payload var)
30973     0x11/imm32/alloc-id:fake:payload
30974     0/imm32/name
30975     0/imm32/name
30976     0x11/imm32/alloc-id:fake
30977     Type-int/imm32
30978     1/imm32/some-block-depth
30979     1/imm32/some-stack-offset
30980     0/imm32/no-register
30981     0/imm32/no-register
30982 
30983 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
30984 Single-byte-var-in-mem:  # (payload list var)
30985     0x11/imm32/alloc-id:fake:payload
30986     0x11/imm32/alloc-id:fake
30987     Byte-var-in-mem/imm32
30988     0/imm32/next
30989     0/imm32/next
30990 
30991 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
30992 Byte-var-in-mem:  # (payload var)
30993     0x11/imm32/alloc-id:fake:payload
30994     0/imm32/name
30995     0/imm32/name
30996     0x11/imm32/alloc-id:fake
30997     Type-byte/imm32
30998     1/imm32/some-block-depth
30999     1/imm32/some-stack-offset
31000     0/imm32/no-register
31001     0/imm32/no-register
31002 
31003 Two-args-int-stack-int-reg:  # (payload list var)
31004     0x11/imm32/alloc-id:fake:payload
31005     0x11/imm32/alloc-id:fake
31006     Int-var-in-mem/imm32
31007     0x11/imm32/alloc-id:fake
31008     Single-int-var-in-some-register/imm32/next
31009 
31010 Two-int-args-in-regs:  # (payload list var)
31011     0x11/imm32/alloc-id:fake:payload
31012     0x11/imm32/alloc-id:fake
31013     Int-var-in-some-register/imm32
31014     0x11/imm32/alloc-id:fake
31015     Single-int-var-in-some-register/imm32/next
31016 
31017 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
31018 Two-args-byte-stack-byte-reg:  # (payload list var)
31019     0x11/imm32/alloc-id:fake:payload
31020     0x11/imm32/alloc-id:fake
31021     Byte-var-in-mem/imm32
31022     0x11/imm32/alloc-id:fake
31023     Single-byte-var-in-some-register/imm32/next
31024 
31025 Two-args-int-reg-int-stack:  # (payload list var)
31026     0x11/imm32/alloc-id:fake:payload
31027     0x11/imm32/alloc-id:fake
31028     Int-var-in-some-register/imm32
31029     0x11/imm32/alloc-id:fake
31030     Single-int-var-in-mem/imm32/next
31031 
31032 Two-args-int-eax-int-literal:  # (payload list var)
31033     0x11/imm32/alloc-id:fake:payload
31034     0x11/imm32/alloc-id:fake
31035     Int-var-in-eax/imm32
31036     0x11/imm32/alloc-id:fake
31037     Single-lit-var/imm32/next
31038 
31039 Int-var-and-literal:  # (payload list var)
31040     0x11/imm32/alloc-id:fake:payload
31041     0x11/imm32/alloc-id:fake
31042     Int-var-in-mem/imm32
31043     0x11/imm32/alloc-id:fake
31044     Single-lit-var/imm32/next
31045 
31046 Int-var-in-register-and-literal:  # (payload list var)
31047     0x11/imm32/alloc-id:fake:payload
31048     0x11/imm32/alloc-id:fake
31049     Int-var-in-some-register/imm32
31050     0x11/imm32/alloc-id:fake
31051     Single-lit-var/imm32/next
31052 
31053 Two-float-args-in-regs:  # (payload list var)
31054     0x11/imm32/alloc-id:fake:payload
31055     0x11/imm32/alloc-id:fake
31056     Float-var-in-some-register/imm32
31057     0x11/imm32/alloc-id:fake
31058     Single-float-var-in-some-register/imm32/next
31059 
31060 Two-args-float-reg-float-stack:  # (payload list var)
31061     0x11/imm32/alloc-id:fake:payload
31062     0x11/imm32/alloc-id:fake
31063     Float-var-in-some-register/imm32
31064     0x11/imm32/alloc-id:fake
31065     Single-float-var-in-mem/imm32/next
31066 
31067 Two-args-float-stack-float-reg:  # (payload list var)
31068     0x11/imm32/alloc-id:fake:payload
31069     0x11/imm32/alloc-id:fake
31070     Float-var-in-mem/imm32
31071     0x11/imm32/alloc-id:fake
31072     Single-float-var-in-some-register/imm32/next
31073 
31074 Single-int-var-in-some-register:  # (payload list var)
31075     0x11/imm32/alloc-id:fake:payload
31076     0x11/imm32/alloc-id:fake
31077     Int-var-in-some-register/imm32
31078     0/imm32/next
31079     0/imm32/next
31080 
31081 Single-addr-var-in-some-register:  # (payload list var)
31082     0x11/imm32/alloc-id:fake:payload
31083     0x11/imm32/alloc-id:fake
31084     Addr-var-in-some-register/imm32
31085     0/imm32/next
31086     0/imm32/next
31087 
31088 Single-byte-var-in-some-register:  # (payload list var)
31089     0x11/imm32/alloc-id:fake:payload
31090     0x11/imm32/alloc-id:fake
31091     Byte-var-in-some-register/imm32
31092     0/imm32/next
31093     0/imm32/next
31094 
31095 Int-var-in-some-register:  # (payload var)
31096     0x11/imm32/alloc-id:fake:payload
31097     0/imm32/name
31098     0/imm32/name
31099     0x11/imm32/alloc-id:fake
31100     Type-int/imm32
31101     1/imm32/some-block-depth
31102     0/imm32/no-stack-offset
31103     0x11/imm32/alloc-id:fake
31104     Any-register/imm32
31105 
31106 Any-register:  # (payload array byte)
31107     0x11/imm32/alloc-id:fake:payload
31108     1/imm32/size
31109     # data
31110     2a/asterisk
31111 
31112 Addr-var-in-some-register:  # (payload var)
31113     0x11/imm32/alloc-id:fake:payload
31114     0/imm32/name
31115     0/imm32/name
31116     0x11/imm32/alloc-id:fake
31117     Type-addr/imm32
31118     1/imm32/some-block-depth
31119     0/imm32/no-stack-offset
31120     0x11/imm32/alloc-id:fake
31121     Any-register/imm32
31122 
31123 Byte-var-in-some-register:  # (payload var)
31124     0x11/imm32/alloc-id:fake:payload
31125     0/imm32/name
31126     0/imm32/name
31127     0x11/imm32/alloc-id:fake
31128     Type-byte/imm32
31129     1/imm32/some-block-depth
31130     0/imm32/no-stack-offset
31131     0x11/imm32/alloc-id:fake
31132     Any-register/imm32
31133 
31134 Single-int-var-in-eax:  # (payload list var)
31135     0x11/imm32/alloc-id:fake:payload
31136     0x11/imm32/alloc-id:fake
31137     Int-var-in-eax/imm32
31138     0/imm32/next
31139     0/imm32/next
31140 
31141 Int-var-in-eax:
31142     0x11/imm32/alloc-id:fake:payload
31143     0/imm32/name
31144     0/imm32/name
31145     0x11/imm32/alloc-id:fake
31146     Type-int/imm32
31147     1/imm32/some-block-depth
31148     0/imm32/no-stack-offset
31149     0x11/imm32/alloc-id:fake
31150     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
31151 
31152 Single-int-var-in-ecx:  # (payload list var)
31153     0x11/imm32/alloc-id:fake:payload
31154     0x11/imm32/alloc-id:fake
31155     Int-var-in-ecx/imm32
31156     0/imm32/next
31157     0/imm32/next
31158 
31159 Int-var-in-ecx:
31160     0x11/imm32/alloc-id:fake:payload
31161     0/imm32/name
31162     0/imm32/name
31163     0x11/imm32/alloc-id:fake
31164     Type-int/imm32
31165     1/imm32/some-block-depth
31166     0/imm32/no-stack-offset
31167     0x11/imm32/alloc-id:fake
31168     $Register-ecx/imm32/register
31169 
31170 Single-int-var-in-edx:  # (payload list var)
31171     0x11/imm32/alloc-id:fake:payload
31172     0x11/imm32/alloc-id:fake
31173     Int-var-in-edx/imm32
31174     0/imm32/next
31175     0/imm32/next
31176 
31177 Int-var-in-edx:  # (payload list var)
31178     0x11/imm32/alloc-id:fake:payload
31179     0/imm32/name
31180     0/imm32/name
31181     0x11/imm32/alloc-id:fake
31182     Type-int/imm32
31183     1/imm32/some-block-depth
31184     0/imm32/no-stack-offset
31185     0x11/imm32/alloc-id:fake
31186     $Register-edx/imm32/register
31187 
31188 Single-int-var-in-ebx:  # (payload list var)
31189     0x11/imm32/alloc-id:fake:payload
31190     0x11/imm32/alloc-id:fake
31191     Int-var-in-ebx/imm32
31192     0/imm32/next
31193     0/imm32/next
31194 
31195 Int-var-in-ebx:  # (payload list var)
31196     0x11/imm32/alloc-id:fake:payload
31197     0/imm32/name
31198     0/imm32/name
31199     0x11/imm32/alloc-id:fake
31200     Type-int/imm32
31201     1/imm32/some-block-depth
31202     0/imm32/no-stack-offset
31203     0x11/imm32/alloc-id:fake
31204     $Register-ebx/imm32/register
31205 
31206 Single-int-var-in-esi:  # (payload list var)
31207     0x11/imm32/alloc-id:fake:payload
31208     0x11/imm32/alloc-id:fake
31209     Int-var-in-esi/imm32
31210     0/imm32/next
31211     0/imm32/next
31212 
31213 Int-var-in-esi:  # (payload list var)
31214     0x11/imm32/alloc-id:fake:payload
31215     0/imm32/name
31216     0/imm32/name
31217     0x11/imm32/alloc-id:fake
31218     Type-int/imm32
31219     1/imm32/some-block-depth
31220     0/imm32/no-stack-offset
31221     0x11/imm32/alloc-id:fake
31222     $Register-esi/imm32/register
31223 
31224 Single-int-var-in-edi:  # (payload list var)
31225     0x11/imm32/alloc-id:fake:payload
31226     0x11/imm32/alloc-id:fake
31227     Int-var-in-edi/imm32
31228     0/imm32/next
31229     0/imm32/next
31230 
31231 Int-var-in-edi:  # (payload list var)
31232     0x11/imm32/alloc-id:fake:payload
31233     0/imm32/name
31234     0/imm32/name
31235     0x11/imm32/alloc-id:fake
31236     Type-int/imm32
31237     1/imm32/some-block-depth
31238     0/imm32/no-stack-offset
31239     0x11/imm32/alloc-id:fake
31240     $Register-edi/imm32/register
31241 
31242 Single-lit-var:  # (payload list var)
31243     0x11/imm32/alloc-id:fake:payload
31244     0x11/imm32/alloc-id:fake
31245     Lit-var/imm32
31246     0/imm32/next
31247     0/imm32/next
31248 
31249 Lit-var:  # (payload var)
31250     0x11/imm32/alloc-id:fake:payload
31251     0/imm32/name
31252     0/imm32/name
31253     0x11/imm32/alloc-id:fake
31254     Type-literal/imm32
31255     1/imm32/some-block-depth
31256     0/imm32/no-stack-offset
31257     0/imm32/no-register
31258     0/imm32/no-register
31259 
31260 Single-float-var-in-mem:  # (payload list var)
31261     0x11/imm32/alloc-id:fake:payload
31262     0x11/imm32/alloc-id:fake
31263     Float-var-in-mem/imm32
31264     0/imm32/next
31265     0/imm32/next
31266 
31267 Float-var-in-mem:  # (payload var)
31268     0x11/imm32/alloc-id:fake:payload
31269     0/imm32/name
31270     0/imm32/name
31271     0x11/imm32/alloc-id:fake
31272     Type-float/imm32
31273     1/imm32/some-block-depth
31274     1/imm32/some-stack-offset
31275     0/imm32/no-register
31276     0/imm32/no-register
31277 
31278 Single-float-var-in-some-register:  # (payload list var)
31279     0x11/imm32/alloc-id:fake:payload
31280     0x11/imm32/alloc-id:fake
31281     Float-var-in-some-register/imm32
31282     0/imm32/next
31283     0/imm32/next
31284 
31285 Float-var-in-some-register:  # (payload var)
31286     0x11/imm32/alloc-id:fake:payload
31287     0/imm32/name
31288     0/imm32/name
31289     0x11/imm32/alloc-id:fake
31290     Type-float/imm32
31291     1/imm32/some-block-depth
31292     0/imm32/no-stack-offset
31293     0x11/imm32/alloc-id:fake
31294     Any-register/imm32
31295 
31296 Type-int:  # (payload type-tree)
31297     0x11/imm32/alloc-id:fake:payload
31298     1/imm32/is-atom
31299     1/imm32/value:int
31300     0/imm32/left:unused
31301     0/imm32/right:null
31302     0/imm32/right:null
31303 
31304 Type-literal:  # (payload type-tree)
31305     0x11/imm32/alloc-id:fake:payload
31306     1/imm32/is-atom
31307     0/imm32/value:literal
31308     0/imm32/left:unused
31309     0/imm32/right:null
31310     0/imm32/right:null
31311 
31312 Type-addr:  # (payload type-tree)
31313     0x11/imm32/alloc-id:fake:payload
31314     1/imm32/is-atom
31315     2/imm32/value:addr
31316     0/imm32/left:unused
31317     0/imm32/right:null
31318     0/imm32/right:null
31319 
31320 Type-byte:  # (payload type-tree)
31321     0x11/imm32/alloc-id:fake:payload
31322     1/imm32/is-atom
31323     8/imm32/value:byte
31324     0/imm32/left:unused
31325     0/imm32/right:null
31326     0/imm32/right:null
31327 
31328 Type-float:  # (payload type-tree)
31329     0x11/imm32/alloc-id:fake:payload
31330     1/imm32/is-atom
31331     0xf/imm32/value:float
31332     0/imm32/left:unused
31333     0/imm32/right:null
31334     0/imm32/right:null
31335 
31336 == code
31337 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
31338     # . prologue
31339     55/push-ebp
31340     89/<- %ebp 4/r32/esp
31341     # . save registers
31342     50/push-eax
31343     51/push-ecx
31344     # ecx = primitive
31345     8b/-> *(ebp+0x10) 1/r32/ecx
31346     # emit primitive name
31347     (emit-indent *(ebp+8) *Curr-block-depth)
31348     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
31349     (write-buffered *(ebp+8) %eax)
31350     # emit rm32 if necessary
31351     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
31352     # emit xm32 if necessary
31353     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
31354     # emit r32 if necessary
31355     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
31356     # emit x32 if necessary
31357     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
31358     # emit imm32 if necessary
31359     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
31360     # emit imm8 if necessary
31361     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
31362     # emit disp32 if necessary
31363     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
31364     (write-buffered *(ebp+8) Newline)
31365 $emit-subx-primitive:end:
31366     # . restore registers
31367     59/pop-to-ecx
31368     58/pop-to-eax
31369     # . epilogue
31370     89/<- %esp 5/r32/ebp
31371     5d/pop-to-ebp
31372     c3/return
31373 
31374 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
31375     # . prologue
31376     55/push-ebp
31377     89/<- %ebp 4/r32/esp
31378     # . save registers
31379     50/push-eax
31380     # if (l == 0) return
31381     81 7/subop/compare *(ebp+0xc) 0/imm32
31382     74/jump-if-= $emit-subx-rm32:end/disp8
31383     # var v/eax: (addr stmt-var)
31384     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
31385     (emit-subx-var-as-rm32 *(ebp+8) %eax)
31386 $emit-subx-rm32:end:
31387     # . restore registers
31388     58/pop-to-eax
31389     # . epilogue
31390     89/<- %esp 5/r32/ebp
31391     5d/pop-to-ebp
31392     c3/return
31393 
31394 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)
31395     # . prologue
31396     55/push-ebp
31397     89/<- %ebp 4/r32/esp
31398     # . save registers
31399     51/push-ecx
31400     # eax = l
31401     8b/-> *(ebp+0xc) 0/r32/eax
31402     # ecx = stmt
31403     8b/-> *(ebp+8) 1/r32/ecx
31404     # if (l == 1) return stmt->inouts
31405     {
31406       3d/compare-eax-and 1/imm32
31407       75/jump-if-!= break/disp8
31408 $get-stmt-operand-from-arg-location:1:
31409       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
31410       eb/jump $get-stmt-operand-from-arg-location:end/disp8
31411     }
31412     # if (l == 2) return stmt->inouts->next
31413     {
31414       3d/compare-eax-and 2/imm32
31415       75/jump-if-!= break/disp8
31416 $get-stmt-operand-from-arg-location:2:
31417       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
31418       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
31419       eb/jump $get-stmt-operand-from-arg-location:end/disp8
31420     }
31421     # if (l == 3) return stmt->outputs
31422     {
31423       3d/compare-eax-and 3/imm32
31424       75/jump-if-!= break/disp8
31425 $get-stmt-operand-from-arg-location:3:
31426       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
31427       eb/jump $get-stmt-operand-from-arg-location:end/disp8
31428     }
31429     # abort
31430     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
31431 $get-stmt-operand-from-arg-location:end:
31432     # . restore registers
31433     59/pop-to-ecx
31434     # . epilogue
31435     89/<- %esp 5/r32/ebp
31436     5d/pop-to-ebp
31437     c3/return
31438 
31439 $get-stmt-operand-from-arg-location:abort:
31440     # error("invalid arg-location " eax)
31441     (write-buffered *(ebp+0x10) "invalid arg-location ")
31442     (write-int32-hex-buffered *(ebp+0x10) %eax)
31443     (write-buffered *(ebp+0x10) Newline)
31444     (flush *(ebp+0x10))
31445     (stop *(ebp+0x14) 1)
31446     # never gets here
31447 
31448 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
31449     # . prologue
31450     55/push-ebp
31451     89/<- %ebp 4/r32/esp
31452     # . save registers
31453     50/push-eax
31454     51/push-ecx
31455     # if (l == 0) return
31456     81 7/subop/compare *(ebp+0xc) 0/imm32
31457     0f 84/jump-if-= $emit-subx-r32:end/disp32
31458     # var v/eax: (addr stmt-var)
31459     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
31460     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
31461     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
31462 #?     (write-buffered Stderr "looking up ")
31463 #?     (write-buffered Stderr %eax)
31464 #?     (write-buffered Stderr Newline)
31465 #?     (flush Stderr)
31466     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
31467     (write-buffered *(ebp+8) Space)
31468     (write-int32-hex-buffered *(ebp+8) *eax)
31469     (write-buffered *(ebp+8) "/r32")
31470 $emit-subx-r32:end:
31471     # . restore registers
31472     59/pop-to-ecx
31473     58/pop-to-eax
31474     # . epilogue
31475     89/<- %esp 5/r32/ebp
31476     5d/pop-to-ebp
31477     c3/return
31478 
31479 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
31480     # . prologue
31481     55/push-ebp
31482     89/<- %ebp 4/r32/esp
31483     # . save registers
31484     50/push-eax
31485     51/push-ecx
31486     # if (l == 0) return
31487     81 7/subop/compare *(ebp+0xc) 0/imm32
31488     0f 84/jump-if-= $emit-subx-x32:end/disp32
31489     # var v/eax: (addr stmt-var)
31490     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
31491     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
31492     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
31493 #?     (write-buffered Stderr "looking up ")
31494 #?     (write-buffered Stderr %eax)
31495 #?     (write-buffered Stderr Newline)
31496 #?     (flush Stderr)
31497     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
31498     (write-buffered *(ebp+8) Space)
31499     (write-int32-hex-buffered *(ebp+8) *eax)
31500     (write-buffered *(ebp+8) "/x32")
31501 $emit-subx-x32:end:
31502     # . restore registers
31503     59/pop-to-ecx
31504     58/pop-to-eax
31505     # . epilogue
31506     89/<- %esp 5/r32/ebp
31507     5d/pop-to-ebp
31508     c3/return
31509 
31510 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
31511     # . prologue
31512     55/push-ebp
31513     89/<- %ebp 4/r32/esp
31514     # . save registers
31515     50/push-eax
31516     51/push-ecx
31517     # if (l == 0) return
31518     81 7/subop/compare *(ebp+0xc) 0/imm32
31519     0f 84/jump-if-= $emit-subx-imm32:end/disp32
31520     # var v/eax: (handle var)
31521     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
31522     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
31523     (lookup *eax *(eax+4))  # Var-name Var-name => eax
31524     (write-buffered *(ebp+8) Space)
31525     (write-buffered *(ebp+8) %eax)
31526     (write-buffered *(ebp+8) "/imm32")
31527 $emit-subx-imm32:end:
31528     # . restore registers
31529     59/pop-to-ecx
31530     58/pop-to-eax
31531     # . epilogue
31532     89/<- %esp 5/r32/ebp
31533     5d/pop-to-ebp
31534     c3/return
31535 
31536 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
31537     # . prologue
31538     55/push-ebp
31539     89/<- %ebp 4/r32/esp
31540     # . save registers
31541     50/push-eax
31542     51/push-ecx
31543     # if (l == 0) return
31544     81 7/subop/compare *(ebp+0xc) 0/imm32
31545     0f 84/jump-if-= $emit-subx-imm32:end/disp32
31546     # var v/eax: (handle var)
31547     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
31548     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
31549     (lookup *eax *(eax+4))  # Var-name Var-name => eax
31550     (write-buffered *(ebp+8) Space)
31551     (write-buffered *(ebp+8) %eax)
31552     (write-buffered *(ebp+8) "/imm8")
31553 $emit-subx-imm8:end:
31554     # . restore registers
31555     59/pop-to-ecx
31556     58/pop-to-eax
31557     # . epilogue
31558     89/<- %esp 5/r32/ebp
31559     5d/pop-to-ebp
31560     c3/return
31561 
31562 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
31563     # . prologue
31564     55/push-ebp
31565     89/<- %ebp 4/r32/esp
31566     # . save registers
31567     50/push-eax
31568     51/push-ecx
31569     # if (location == 0) return
31570     81 7/subop/compare *(ebp+0xc) 0/imm32
31571     0f 84/jump-if-= $emit-subx-disp32:end/disp32
31572     # var v/eax: (addr stmt-var)
31573     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
31574     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
31575     (lookup *eax *(eax+4))  # Var-name Var-name => eax
31576     (write-buffered *(ebp+8) Space)
31577     (write-buffered *(ebp+8) %eax)
31578     # hack: if instruction operation starts with "break", emit ":break"
31579     # var name/ecx: (addr array byte) = lookup(stmt->operation)
31580     8b/-> *(ebp+0x10) 0/r32/eax
31581     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
31582     89/<- %ecx 0/r32/eax
31583     {
31584       (string-starts-with? %ecx "break")  # => eax
31585       3d/compare-eax-and 0/imm32/false
31586       74/jump-if-= break/disp8
31587       (write-buffered *(ebp+8) ":break")
31588     }
31589     # hack: if instruction operation starts with "loop", emit ":loop"
31590     {
31591       (string-starts-with? %ecx "loop")  # => eax
31592       3d/compare-eax-and 0/imm32/false
31593       74/jump-if-= break/disp8
31594       (write-buffered *(ebp+8) ":loop")
31595     }
31596     (write-buffered *(ebp+8) "/disp32")
31597 $emit-subx-disp32:end:
31598     # . restore registers
31599     59/pop-to-ecx
31600     58/pop-to-eax
31601     # . epilogue
31602     89/<- %esp 5/r32/ebp
31603     5d/pop-to-ebp
31604     c3/return
31605 
31606 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
31607     # . prologue
31608     55/push-ebp
31609     89/<- %ebp 4/r32/esp
31610     # . save registers
31611     50/push-eax
31612     51/push-ecx
31613     #
31614     (emit-indent *(ebp+8) *Curr-block-depth)
31615     (write-buffered *(ebp+8) "(")
31616     # ecx = stmt
31617     8b/-> *(ebp+0xc) 1/r32/ecx
31618     # - emit function name
31619     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
31620     (write-buffered *(ebp+8) %eax)
31621     # - emit arguments
31622     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
31623     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
31624     {
31625       # if (curr == null) break
31626       3d/compare-eax-and 0/imm32
31627       74/jump-if-= break/disp8
31628       #
31629       (emit-subx-call-operand *(ebp+8) %eax)
31630       # curr = lookup(curr->next)
31631       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
31632       eb/jump loop/disp8
31633     }
31634     #
31635     (write-buffered *(ebp+8) ")\n")
31636 $emit-call:end:
31637     # . restore registers
31638     59/pop-to-ecx
31639     58/pop-to-eax
31640     # . epilogue
31641     89/<- %esp 5/r32/ebp
31642     5d/pop-to-ebp
31643     c3/return
31644 
31645 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
31646     # shares code with emit-subx-var-as-rm32
31647     # . prologue
31648     55/push-ebp
31649     89/<- %ebp 4/r32/esp
31650     # . save registers
31651     50/push-eax
31652     51/push-ecx
31653     56/push-esi
31654     # ecx = s
31655     8b/-> *(ebp+0xc) 1/r32/ecx
31656     # var operand/esi: (addr var) = lookup(s->value)
31657     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
31658     89/<- %esi 0/r32/eax
31659     # if (operand->register && !s->is-deref?) emit "%__"
31660     {
31661 $emit-subx-call-operand:check-for-register-direct:
31662       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31663       74/jump-if-= break/disp8
31664       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31665       75/jump-if-!= break/disp8
31666 $emit-subx-call-operand:register-direct:
31667       (write-buffered *(ebp+8) " %")
31668       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31669       (write-buffered *(ebp+8) %eax)
31670       e9/jump $emit-subx-call-operand:end/disp32
31671     }
31672     # else if (operand->register && s->is-deref?) emit "*__"
31673     {
31674 $emit-subx-call-operand:check-for-register-indirect:
31675       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31676       74/jump-if-= break/disp8
31677       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31678       74/jump-if-= break/disp8
31679 $emit-subx-call-operand:register-indirect:
31680       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
31681       e9/jump $emit-subx-call-operand:end/disp32
31682     }
31683     # else if (operand->stack-offset) emit "*(ebp+__)"
31684     {
31685       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
31686       74/jump-if-= break/disp8
31687 $emit-subx-call-operand:stack:
31688       (emit-subx-call-operand-stack *(ebp+8) %esi)
31689       e9/jump $emit-subx-call-operand:end/disp32
31690     }
31691     # else if (operand->type == literal) emit "__"
31692     {
31693       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
31694       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
31695       75/jump-if-!= break/disp8
31696 $emit-subx-call-operand:literal:
31697       (write-buffered *(ebp+8) Space)
31698       (lookup *esi *(esi+4))  # Var-name Var-name => eax
31699       (write-buffered *(ebp+8) %eax)
31700       e9/jump $emit-subx-call-operand:end/disp32
31701     }
31702     # else if (operand->type == literal-string) emit "__"
31703     {
31704       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
31705       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
31706       75/jump-if-!= break/disp8
31707 $emit-subx-call-operand:literal-string:
31708       (write-buffered *(ebp+8) Space)
31709       (lookup *esi *(esi+4))  # Var-name Var-name => eax
31710       (write-buffered *(ebp+8) %eax)
31711     }
31712 $emit-subx-call-operand:end:
31713     # . restore registers
31714     5e/pop-to-esi
31715     59/pop-to-ecx
31716     58/pop-to-eax
31717     # . epilogue
31718     89/<- %esp 5/r32/ebp
31719     5d/pop-to-ebp
31720     c3/return
31721 
31722 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
31723     # . prologue
31724     55/push-ebp
31725     89/<- %ebp 4/r32/esp
31726     # . save registers
31727     50/push-eax
31728     51/push-ecx
31729     56/push-esi
31730     # esi = v
31731     8b/-> *(ebp+0xc) 6/r32/esi
31732     # var size/ecx: int = size-of-deref(v)
31733     (size-of-deref %esi)  # => eax
31734     89/<- %ecx 0/r32/eax
31735     # var reg-name/esi: (addr array byte) = lookup(v->register)
31736     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31737     89/<- %esi 0/r32/eax
31738     # TODO: assert size is a multiple of 4
31739     # var i/eax: int = 0
31740     b8/copy-to-eax 0/imm32
31741     {
31742 $emit-subx-call-operand-register-indirect:loop:
31743       # if (i >= size) break
31744       39/compare %eax 1/r32/ecx
31745       7d/jump-if->= break/disp8
31746       # emit " *(" v->register "+" i ")"
31747       (write-buffered *(ebp+8) " *(")
31748       (write-buffered *(ebp+8) %esi)
31749       (write-buffered *(ebp+8) "+")
31750       (write-int32-hex-buffered *(ebp+8) %eax)
31751       (write-buffered *(ebp+8) ")")
31752       # i += 4
31753       05/add-to-eax 4/imm32
31754       #
31755       eb/jump loop/disp8
31756     }
31757 $emit-subx-call-operand-register-indirect:end:
31758     # . restore registers
31759     5e/pop-to-esi
31760     59/pop-to-ecx
31761     58/pop-to-eax
31762     # . epilogue
31763     89/<- %esp 5/r32/ebp
31764     5d/pop-to-ebp
31765     c3/return
31766 
31767 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
31768     # . prologue
31769     55/push-ebp
31770     89/<- %ebp 4/r32/esp
31771     # . save registers
31772     50/push-eax
31773     51/push-ecx
31774     56/push-esi
31775     # esi = v
31776     8b/-> *(ebp+0xc) 6/r32/esi
31777     # var curr/ecx: int = v->offset
31778     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
31779     # var max/eax: int = v->offset + size-of(v)
31780     (size-of %esi)  # => eax
31781     # TODO: assert size is a multiple of 4
31782     01/add-to %eax 1/r32/ecx
31783     {
31784 $emit-subx-call-operand-stack:loop:
31785       # if (curr >= max) break
31786       39/compare %ecx 0/r32/eax
31787       7d/jump-if->= break/disp8
31788       # emit " *(ebp+" curr ")"
31789       (write-buffered *(ebp+8) " *(ebp+")
31790       (write-int32-hex-buffered *(ebp+8) %ecx)
31791       (write-buffered *(ebp+8) ")")
31792       # i += 4
31793       81 0/subop/add %ecx 4/imm32
31794       #
31795       eb/jump loop/disp8
31796     }
31797 $emit-subx-call-operand-stack:end:
31798     # . restore registers
31799     5e/pop-to-esi
31800     59/pop-to-ecx
31801     58/pop-to-eax
31802     # . epilogue
31803     89/<- %esp 5/r32/ebp
31804     5d/pop-to-ebp
31805     c3/return
31806 
31807 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
31808     # . prologue
31809     55/push-ebp
31810     89/<- %ebp 4/r32/esp
31811     # . save registers
31812     50/push-eax
31813     51/push-ecx
31814     56/push-esi
31815     # ecx = s
31816     8b/-> *(ebp+0xc) 1/r32/ecx
31817     # var operand/esi: (addr var) = lookup(s->value)
31818     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
31819     89/<- %esi 0/r32/eax
31820     # if (operand->register && s->is-deref?) emit "*__"
31821     {
31822 $emit-subx-var-as-rm32:check-for-register-indirect:
31823       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31824       74/jump-if-= break/disp8
31825       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31826       74/jump-if-= break/disp8
31827 $emit-subx-var-as-rm32:register-indirect:
31828       (write-buffered *(ebp+8) " *")
31829       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31830       (write-buffered *(ebp+8) %eax)
31831       e9/jump $emit-subx-var-as-rm32:end/disp32
31832     }
31833     # if (operand->register && !s->is-deref?) emit "%__"
31834     {
31835 $emit-subx-var-as-rm32:check-for-register-direct:
31836       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
31837       74/jump-if-= break/disp8
31838       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
31839       75/jump-if-!= break/disp8
31840 $emit-subx-var-as-rm32:register-direct:
31841       (write-buffered *(ebp+8) " %")
31842       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
31843       (write-buffered *(ebp+8) %eax)
31844       e9/jump $emit-subx-var-as-rm32:end/disp32
31845     }
31846     # else if (operand->stack-offset) emit "*(ebp+__)"
31847     {
31848       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
31849       74/jump-if-= break/disp8
31850 $emit-subx-var-as-rm32:stack:
31851       (write-buffered *(ebp+8) Space)
31852       (write-buffered *(ebp+8) "*(ebp+")
31853       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
31854       (write-buffered *(ebp+8) ")")
31855     }
31856 $emit-subx-var-as-rm32:end:
31857     # . restore registers
31858     5e/pop-to-esi
31859     59/pop-to-ecx
31860     58/pop-to-eax
31861     # . epilogue
31862     89/<- %esp 5/r32/ebp
31863     5d/pop-to-ebp
31864     c3/return
31865 
31866 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
31867     # . prologue
31868     55/push-ebp
31869     89/<- %ebp 4/r32/esp
31870     # . save registers
31871     51/push-ecx
31872     # var curr/ecx: (addr primitive) = primitives
31873     8b/-> *(ebp+8) 1/r32/ecx
31874     {
31875 $find-matching-primitive:loop:
31876       # if (curr == null) break
31877       81 7/subop/compare %ecx 0/imm32
31878       74/jump-if-= break/disp8
31879       # if match(curr, stmt) return curr
31880       {
31881         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
31882         3d/compare-eax-and 0/imm32/false
31883         74/jump-if-= break/disp8
31884         89/<- %eax 1/r32/ecx
31885         eb/jump $find-matching-primitive:end/disp8
31886       }
31887 $find-matching-primitive:next-primitive:
31888       # curr = curr->next
31889       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
31890       89/<- %ecx 0/r32/eax
31891       #
31892       e9/jump loop/disp32
31893     }
31894     # return null
31895     b8/copy-to-eax 0/imm32
31896 $find-matching-primitive:end:
31897     # . restore registers
31898     59/pop-to-ecx
31899     # . epilogue
31900     89/<- %esp 5/r32/ebp
31901     5d/pop-to-ebp
31902     c3/return
31903 
31904 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
31905     # A mu stmt matches a primitive if the name matches, all the inout vars
31906     # match, and all the output vars match.
31907     # Vars match if types match and registers match.
31908     # In addition, a stmt output matches a primitive's output if types match
31909     # and the primitive has a wildcard register.
31910     # . prologue
31911     55/push-ebp
31912     89/<- %ebp 4/r32/esp
31913     # . save registers
31914     51/push-ecx
31915     52/push-edx
31916     53/push-ebx
31917     56/push-esi
31918     57/push-edi
31919     # ecx = stmt
31920     8b/-> *(ebp+8) 1/r32/ecx
31921     # edx = primitive
31922     8b/-> *(ebp+0xc) 2/r32/edx
31923     {
31924 $mu-stmt-matches-primitive?:check-name:
31925       # if (primitive->name != stmt->operation) return false
31926       # . var esi: (addr array byte) = lookup(stmt->operation)
31927       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
31928       89/<- %esi 0/r32/eax
31929       # . var edi: (addr array byte) = lookup(primitive->name)
31930       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
31931 #?       (write-buffered Stderr %eax)
31932 #?       (write-buffered Stderr Newline)
31933 #?       (flush Stderr)
31934       89/<- %edi 0/r32/eax
31935       (string-equal? %esi %edi)  # => eax
31936       3d/compare-eax-and 0/imm32/false
31937       75/jump-if-!= break/disp8
31938       b8/copy-to-eax 0/imm32
31939       e9/jump $mu-stmt-matches-primitive?:end/disp32
31940     }
31941     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
31942     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
31943     89/<- %esi 0/r32/eax
31944     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
31945     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
31946     89/<- %edi 0/r32/eax
31947     {
31948 $mu-stmt-matches-primitive?:inouts-loop:
31949       # if (curr == 0 && curr2 == 0) move on to check outputs
31950       {
31951 $mu-stmt-matches-primitive?:check-both-inouts-null:
31952         81 7/subop/compare %esi 0/imm32
31953         75/jump-if-!= break/disp8
31954 $mu-stmt-matches-primitive?:stmt-inout-null:
31955         81 7/subop/compare %edi 0/imm32
31956         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
31957 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
31958         # return false
31959         b8/copy-to-eax 0/imm32/false
31960         e9/jump $mu-stmt-matches-primitive?:end/disp32
31961       }
31962       # if (curr2 == 0) return false
31963       {
31964 $mu-stmt-matches-primitive?:check-prim-inout-null:
31965         81 7/subop/compare %edi 0/imm32
31966         75/jump-if-!= break/disp8
31967 $mu-stmt-matches-primitive?:prim-inout-null:
31968         b8/copy-to-eax 0/imm32/false
31969         e9/jump $mu-stmt-matches-primitive?:end/disp32
31970       }
31971       # if (curr != curr2) return false
31972       {
31973 $mu-stmt-matches-primitive?:check-inouts-match:
31974         (lookup *edi *(edi+4))  # List-value List-value => eax
31975         (operand-matches-primitive? %esi %eax)  # => eax
31976         3d/compare-eax-and 0/imm32/false
31977         75/jump-if-!= break/disp8
31978 $mu-stmt-matches-primitive?:inouts-match:
31979         b8/copy-to-eax 0/imm32/false
31980         e9/jump $mu-stmt-matches-primitive?:end/disp32
31981       }
31982 $mu-stmt-matches-primitive?:next-inout:
31983       # curr = lookup(curr->next)
31984       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
31985       89/<- %esi 0/r32/eax
31986       # curr2 = lookup(curr2->next)
31987       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
31988       89/<- %edi 0/r32/eax
31989       #
31990       e9/jump loop/disp32
31991     }
31992 $mu-stmt-matches-primitive?:check-outputs:
31993     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
31994     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
31995     89/<- %esi 0/r32/eax
31996     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
31997     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
31998     89/<- %edi 0/r32/eax
31999     {
32000 $mu-stmt-matches-primitive?:outputs-loop:
32001       # if (curr == 0) return (curr2 == 0)
32002       {
32003 $mu-stmt-matches-primitive?:check-both-outputs-null:
32004         81 7/subop/compare %esi 0/imm32
32005         75/jump-if-!= break/disp8
32006         {
32007 $mu-stmt-matches-primitive?:stmt-output-null:
32008           81 7/subop/compare %edi 0/imm32
32009           75/jump-if-!= break/disp8
32010 $mu-stmt-matches-primitive?:both-outputs-null:
32011           # return true
32012           b8/copy-to-eax 1/imm32
32013           e9/jump $mu-stmt-matches-primitive?:end/disp32
32014         }
32015 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
32016         # return false
32017         b8/copy-to-eax 0/imm32
32018         e9/jump $mu-stmt-matches-primitive?:end/disp32
32019       }
32020       # if (curr2 == 0) return false
32021       {
32022 $mu-stmt-matches-primitive?:check-prim-output-null:
32023         81 7/subop/compare %edi 0/imm32
32024         75/jump-if-!= break/disp8
32025 $mu-stmt-matches-primitive?:prim-output-is-null:
32026         b8/copy-to-eax 0/imm32
32027         e9/jump $mu-stmt-matches-primitive?:end/disp32
32028       }
32029       # if (curr != curr2) return false
32030       {
32031 $mu-stmt-matches-primitive?:check-outputs-match:
32032         (lookup *edi *(edi+4))  # List-value List-value => eax
32033         (operand-matches-primitive? %esi %eax)  # => eax
32034         3d/compare-eax-and 0/imm32/false
32035         75/jump-if-!= break/disp8
32036 $mu-stmt-matches-primitive?:outputs-match:
32037         b8/copy-to-eax 0/imm32
32038         e9/jump $mu-stmt-matches-primitive?:end/disp32
32039       }
32040 $mu-stmt-matches-primitive?:next-output:
32041       # curr = lookup(curr->next)
32042       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
32043       89/<- %esi 0/r32/eax
32044       # curr2 = lookup(curr2->next)
32045       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
32046       89/<- %edi 0/r32/eax
32047       #
32048       e9/jump loop/disp32
32049     }
32050 $mu-stmt-matches-primitive?:return-true:
32051     b8/copy-to-eax 1/imm32
32052 $mu-stmt-matches-primitive?:end:
32053     # . restore registers
32054     5f/pop-to-edi
32055     5e/pop-to-esi
32056     5b/pop-to-ebx
32057     5a/pop-to-edx
32058     59/pop-to-ecx
32059     # . epilogue
32060     89/<- %esp 5/r32/ebp
32061     5d/pop-to-ebp
32062     c3/return
32063 
32064 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
32065     # . prologue
32066     55/push-ebp
32067     89/<- %ebp 4/r32/esp
32068     # . save registers
32069     51/push-ecx
32070     52/push-edx
32071     53/push-ebx
32072     56/push-esi
32073     57/push-edi
32074     # ecx = s
32075     8b/-> *(ebp+8) 1/r32/ecx
32076     # var var/esi: (addr var) = lookup(s->value)
32077     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
32078     89/<- %esi 0/r32/eax
32079     # edi = prim-var
32080     8b/-> *(ebp+0xc) 7/r32/edi
32081 $operand-matches-primitive?:check-type:
32082     # if !category-match?(var->type, prim-var->type) return false
32083     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
32084     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
32085     89/<- %ebx 0/r32/eax
32086     # . if s is deref, vtype = vtype->right
32087     {
32088       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32089       74/jump-if-= break/disp8
32090 $operand-matches-primitive?:is-deref:
32091       # . var t/eax: (addr type)
32092       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
32093       # . if !t->is-atom? t = t->left
32094       81 7/subop/compare *eax 0/imm32/false
32095       {
32096         75/jump-if-!= break/disp8
32097         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
32098       }
32099       # .
32100       89/<- %ebx 0/r32/eax
32101     }
32102     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
32103     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
32104     (subx-type-category-match? %ebx %eax)  # => eax
32105     3d/compare-eax-and 0/imm32/false
32106     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
32107     {
32108 $operand-matches-primitive?:check-register:
32109       # if prim-var is in memory and var is in register but dereference, match
32110       {
32111         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
32112         0f 85/jump-if-!= break/disp32
32113         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32114         74/jump-if-= break/disp8
32115         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32116         74/jump-if-= break/disp8
32117 $operand-matches-primitive?:var-deref-match:
32118         e9/jump $operand-matches-primitive?:return-true/disp32
32119       }
32120       # if prim-var is in register and var is in register but dereference, no match
32121       {
32122         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
32123         0f 84/jump-if-= break/disp32
32124         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32125         0f 84/jump-if-= break/disp32
32126         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32127         74/jump-if-= break/disp8
32128 $operand-matches-primitive?:var-deref-no-match:
32129         e9/jump $operand-matches-primitive?:return-false/disp32
32130       }
32131       # return false if var->register doesn't match prim-var->register
32132       {
32133         # if register addresses are equal, it's a match
32134         # var vreg/ebx: (addr array byte) = lookup(var->register)
32135         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32136         89/<- %ebx 0/r32/eax
32137         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
32138         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
32139         89/<- %ecx 0/r32/eax
32140         # if (vreg == preg) break
32141         39/compare %ecx 3/r32/ebx
32142         74/jump-if-= break/disp8
32143 $operand-matches-primitive?:var-register-no-match:
32144         # if either address is 0, return false
32145         81 7/subop/compare %ebx 0/imm32
32146         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
32147         81 7/subop/compare %ecx 0/imm32
32148         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
32149         # if prim-var->register is wildcard, it's a match
32150         (string-equal? %ecx "*")  # Any-register => eax
32151         3d/compare-eax-and 0/imm32/false
32152         75/jump-if-!= break/disp8
32153 $operand-matches-primitive?:wildcard-no-match:
32154         # if string contents aren't equal, return false
32155         (string-equal? %ecx %ebx)  # => eax
32156         3d/compare-eax-and 0/imm32/false
32157         74/jump-if-= $operand-matches-primitive?:return-false/disp8
32158       }
32159     }
32160 $operand-matches-primitive?:return-true:
32161     b8/copy-to-eax 1/imm32/true
32162     eb/jump $operand-matches-primitive?:end/disp8
32163 $operand-matches-primitive?:return-false:
32164     b8/copy-to-eax 0/imm32/false
32165 $operand-matches-primitive?:end:
32166     # . restore registers
32167     5f/pop-to-edi
32168     5e/pop-to-esi
32169     5b/pop-to-ebx
32170     5a/pop-to-edx
32171     59/pop-to-ecx
32172     # . epilogue
32173     89/<- %esp 5/r32/ebp
32174     5d/pop-to-ebp
32175     c3/return
32176 
32177 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
32178     # . prologue
32179     55/push-ebp
32180     89/<- %ebp 4/r32/esp
32181     # . save registers
32182     51/push-ecx
32183     # var curr/ecx: (handle function) = functions
32184     8b/-> *(ebp+8) 1/r32/ecx
32185     {
32186       # if (curr == null) break
32187       81 7/subop/compare %ecx 0/imm32
32188       74/jump-if-= break/disp8
32189 #?       (write-buffered Stderr "iter\n")
32190 #?       (flush Stderr)
32191       # if match(stmt, curr) return curr
32192       {
32193         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
32194         3d/compare-eax-and 0/imm32/false
32195         74/jump-if-= break/disp8
32196         89/<- %eax 1/r32/ecx
32197         eb/jump $find-matching-function:end/disp8
32198       }
32199       # curr = curr->next
32200       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
32201       89/<- %ecx 0/r32/eax
32202       #
32203       eb/jump loop/disp8
32204     }
32205     # return null
32206     b8/copy-to-eax 0/imm32
32207 $find-matching-function:end:
32208     # . restore registers
32209     59/pop-to-ecx
32210     # . epilogue
32211     89/<- %esp 5/r32/ebp
32212     5d/pop-to-ebp
32213     c3/return
32214 
32215 # Just compare names; user-defined functions don't support overloading yet.
32216 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
32217     # . prologue
32218     55/push-ebp
32219     89/<- %ebp 4/r32/esp
32220     # . save registers
32221     51/push-ecx
32222     # return function->name == stmt->operation
32223     # ecx = lookup(stmt->operation)
32224     8b/-> *(ebp+8) 0/r32/eax
32225     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
32226     89/<- %ecx 0/r32/eax
32227     # eax = lookup(function->name)
32228     8b/-> *(ebp+0xc) 0/r32/eax
32229     (lookup *eax *(eax+4))  # Function-name Function-name => eax
32230     (string-equal? %eax %ecx)  # => eax
32231 $mu-stmt-matches-function?:end:
32232     # . restore registers
32233     59/pop-to-ecx
32234     # . epilogue
32235     89/<- %esp 5/r32/ebp
32236     5d/pop-to-ebp
32237     c3/return
32238 
32239 # Type-checking happens elsewhere. This method is for selecting between
32240 # primitives.
32241 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
32242     # . prologue
32243     55/push-ebp
32244     89/<- %ebp 4/r32/esp
32245     # . save registers
32246     51/push-ecx
32247     # var cata/ecx: int = type-category(a)
32248     (type-category *(ebp+8))  # => eax
32249     89/<- %ecx 0/r32/eax
32250     # var catb/eax: int = type-category(b)
32251     (type-category *(ebp+0xc))  # => eax
32252     # return cata == catb
32253     39/compare %eax 1/r32/ecx
32254     0f 94/set-byte-if-= %al
32255     81 4/subop/and %eax 0xff/imm32
32256 $subx-type-category-match?:end:
32257     # . restore registers
32258     59/pop-to-ecx
32259     # . epilogue
32260     89/<- %esp 5/r32/ebp
32261     5d/pop-to-ebp
32262     c3/return
32263 
32264 type-category:  # a: (addr type-tree) -> result/eax: int
32265     # . prologue
32266     55/push-ebp
32267     89/<- %ebp 4/r32/esp
32268     # . save registers
32269     51/push-ecx
32270     # var lit?/ecx: boolean = is-literal-type?(a)
32271     (is-simple-mu-type? *(ebp+8) 0)  # literal => eax
32272     89/<- %ecx 0/r32/eax
32273     # var float?/eax: int = is-float?(a)
32274     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
32275     # set bits for lit? and float?
32276     c1/shift 4/subop/left %ecx 1/imm8
32277     09/or %eax 1/r32/ecx
32278 $type-category:end:
32279     # . restore registers
32280     59/pop-to-ecx
32281     # . epilogue
32282     89/<- %esp 5/r32/ebp
32283     5d/pop-to-ebp
32284     c3/return
32285 
32286 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
32287     # . prologue
32288     55/push-ebp
32289     89/<- %ebp 4/r32/esp
32290     # . save registers
32291     51/push-ecx
32292     # ecx = n
32293     8b/-> *(ebp+0xc) 1/r32/ecx
32294     # return (a->value == n)
32295     8b/-> *(ebp+8) 0/r32/eax
32296     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
32297     0f 94/set-byte-if-= %al
32298     81 4/subop/and %eax 0xff/imm32
32299 $is-simple-mu-type?:end:
32300     # . restore registers
32301     59/pop-to-ecx
32302     # . epilogue
32303     89/<- %esp 5/r32/ebp
32304     5d/pop-to-ebp
32305     c3/return
32306 
32307 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
32308     # . prologue
32309     55/push-ebp
32310     89/<- %ebp 4/r32/esp
32311     # eax = a
32312     8b/-> *(ebp+8) 0/r32/eax
32313     # if (!a->is-atom?) a = a->left
32314     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
32315     {
32316       75/jump-if-!= break/disp8
32317       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
32318     }
32319     # return (a->value == addr)
32320     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
32321     0f 94/set-byte-if-= %al
32322     81 4/subop/and %eax 0xff/imm32
32323 $is-mu-addr-type?:end:
32324     # . epilogue
32325     89/<- %esp 5/r32/ebp
32326     5d/pop-to-ebp
32327     c3/return
32328 
32329 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
32330     # . prologue
32331     55/push-ebp
32332     89/<- %ebp 4/r32/esp
32333     # eax = a
32334     8b/-> *(ebp+8) 0/r32/eax
32335     # if (!a->is-atom?) a = a->left
32336     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
32337     {
32338       75/jump-if-!= break/disp8
32339       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
32340     }
32341     # return (a->value == array)
32342     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
32343     0f 94/set-byte-if-= %al
32344     81 4/subop/and %eax 0xff/imm32
32345 $is-mu-array-type?:end:
32346     # . epilogue
32347     89/<- %esp 5/r32/ebp
32348     5d/pop-to-ebp
32349     c3/return
32350 
32351 is-mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
32352     # . prologue
32353     55/push-ebp
32354     89/<- %ebp 4/r32/esp
32355     # . save registers
32356     56/push-esi
32357     # esi = a
32358     8b/-> *(ebp+8) 6/r32/esi
32359     # if (a->is-atom?) return false
32360     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
32361     0f 85/jump-if-!= $is-mu-string-type?:return-false/disp32
32362     # if a is not an addr, return false
32363     (is-mu-addr-type? %esi)  # => eax
32364     3d/compare-eax-with 0/imm32/false
32365     0f 84/jump-if-= $is-mu-string-type?:end/disp32  # eax changes var
32366     # if a is not an array, return false
32367     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
32368     (is-mu-array-type? %eax)  # => eax
32369     3d/compare-eax-with 0/imm32/false
32370     74/jump-if-= $is-mu-string-type?:end/disp8  # eax changes var
32371     # var p/eax: (addr type-tree) = payload of a
32372     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
32373     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
32374     # if p is an atom, return false
32375     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
32376     75/jump-if-!= $is-mu-string-type?:return-false/disp8
32377     # return (p == byte)
32378     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
32379     (is-simple-mu-type? %eax 8)  # byte => eax
32380     eb/jump $is-mu-string-type?:end/disp8
32381 $is-mu-string-type?:return-false:
32382     b8/copy-to-eax 0/imm32/false
32383 $is-mu-string-type?:end:
32384     # . restore registers
32385     5e/pop-to-esi
32386     # . epilogue
32387     89/<- %esp 5/r32/ebp
32388     5d/pop-to-ebp
32389     c3/return
32390 
32391 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
32392     # . prologue
32393     55/push-ebp
32394     89/<- %ebp 4/r32/esp
32395     # eax = a
32396     8b/-> *(ebp+8) 0/r32/eax
32397     # if (!a->is-atom?) a = a->left
32398     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
32399     {
32400       75/jump-if-!= break/disp8
32401       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
32402     }
32403     # return (a->value == stream)
32404     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
32405     0f 94/set-byte-if-= %al
32406     81 4/subop/and %eax 0xff/imm32
32407 $is-mu-stream-type?:end:
32408     # . epilogue
32409     89/<- %esp 5/r32/ebp
32410     5d/pop-to-ebp
32411     c3/return
32412 
32413 test-emit-subx-stmt-primitive:
32414     # Primitive operation on a variable on the stack.
32415     #   increment foo
32416     # =>
32417     #   ff 0/subop/increment *(ebp-8)
32418     #
32419     # There's a variable on the var stack as follows:
32420     #   name: 'foo'
32421     #   type: int
32422     #   stack-offset: -8
32423     #
32424     # There's a primitive with this info:
32425     #   name: 'increment'
32426     #   inouts: int/mem
32427     #   value: 'ff 0/subop/increment'
32428     #
32429     # . prologue
32430     55/push-ebp
32431     89/<- %ebp 4/r32/esp
32432     # setup
32433     (clear-stream _test-output-stream)
32434     (clear-stream $_test-output-buffered-file->buffer)
32435     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
32436 $test-emit-subx-stmt-primitive:initialize-type:
32437     # var type/ecx: (payload type-tree) = int
32438     68/push 0/imm32/right:null
32439     68/push 0/imm32/right:null
32440     68/push 0/imm32/left:unused
32441     68/push 1/imm32/value:int
32442     68/push 1/imm32/is-atom?:true
32443     68/push 0x11/imm32/alloc-id:fake:payload
32444     89/<- %ecx 4/r32/esp
32445 $test-emit-subx-stmt-primitive:initialize-var:
32446     # var var-foo/ecx: (payload var) = var(type)
32447     68/push 0/imm32/no-register
32448     68/push 0/imm32/no-register
32449     68/push -8/imm32/stack-offset
32450     68/push 1/imm32/block-depth
32451     51/push-ecx/type
32452     68/push 0x11/imm32/alloc-id:fake
32453     68/push 0/imm32/name
32454     68/push 0/imm32/name
32455     68/push 0x11/imm32/alloc-id:fake:payload
32456     89/<- %ecx 4/r32/esp
32457 $test-emit-subx-stmt-primitive:initialize-var-name:
32458     # var-foo->name = "foo"
32459     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32460     (copy-array Heap "foo" %eax)
32461 $test-emit-subx-stmt-primitive:initialize-stmt-var:
32462     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
32463     68/push 0/imm32/is-deref:false
32464     68/push 0/imm32/next
32465     68/push 0/imm32/next
32466     51/push-ecx/var-foo
32467     68/push 0x11/imm32/alloc-id:fake
32468     68/push 0x11/imm32/alloc-id:fake:payload
32469     89/<- %ebx 4/r32/esp
32470 $test-emit-subx-stmt-primitive:initialize-stmt:
32471     # var stmt/esi: (addr statement)
32472     68/push 0/imm32/no-outputs
32473     68/push 0/imm32/no-outputs
32474     53/push-ebx/inouts
32475     68/push 0x11/imm32/alloc-id:fake
32476     68/push 0/imm32/operation
32477     68/push 0/imm32/operation
32478     68/push 1/imm32/tag
32479     89/<- %esi 4/r32/esp
32480 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
32481     # stmt->operation = "increment"
32482     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32483     (copy-array Heap "increment" %eax)
32484 $test-emit-subx-stmt-primitive:initialize-primitive:
32485     # var primitives/ebx: (addr primitive)
32486     68/push 0/imm32/next
32487     68/push 0/imm32/next
32488     68/push 0/imm32/no-x32
32489     68/push 0/imm32/no-xm32
32490     68/push 0/imm32/no-disp32
32491     68/push 0/imm32/no-imm8
32492     68/push 0/imm32/no-imm32
32493     68/push 0/imm32/no-r32
32494     68/push 1/imm32/rm32-is-first-inout
32495     68/push 0/imm32/subx-name
32496     68/push 0/imm32/subx-name
32497     68/push 0/imm32/no-outputs
32498     68/push 0/imm32/no-outputs
32499     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
32500     68/push 0x11/imm32/alloc-id:fake
32501     68/push 0/imm32/name
32502     68/push 0/imm32/name
32503     89/<- %ebx 4/r32/esp
32504 $test-emit-subx-stmt-primitive:initialize-primitive-name:
32505     # primitives->name = "increment"
32506     (copy-array Heap "increment" %ebx)  # Primitive-name
32507 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
32508     # primitives->subx-name = "ff 0/subop/increment"
32509     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
32510     (copy-array Heap "ff 0/subop/increment" %eax)
32511     # convert
32512     c7 0/subop/copy *Curr-block-depth 0/imm32
32513     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
32514     (flush _test-output-buffered-file)
32515 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
32521     # check output
32522     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
32523     # . epilogue
32524     89/<- %esp 5/r32/ebp
32525     5d/pop-to-ebp
32526     c3/return
32527 
32528 test-emit-subx-stmt-primitive-register:
32529     # Primitive operation on a variable in a register.
32530     #   foo <- increment
32531     # =>
32532     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
32533     #
32534     # There's a variable on the var stack as follows:
32535     #   name: 'foo'
32536     #   type: int
32537     #   register: 'eax'
32538     #
32539     # There's a primitive with this info:
32540     #   name: 'increment'
32541     #   out: int/reg
32542     #   value: 'ff 0/subop/increment'
32543     #
32544     # . prologue
32545     55/push-ebp
32546     89/<- %ebp 4/r32/esp
32547     # setup
32548     (clear-stream _test-output-stream)
32549     (clear-stream $_test-output-buffered-file->buffer)
32550 $test-emit-subx-stmt-primitive-register:initialize-type:
32551     # var type/ecx: (payload type-tree) = int
32552     68/push 0/imm32/right:null
32553     68/push 0/imm32/right:null
32554     68/push 0/imm32/left:unused
32555     68/push 1/imm32/value:int
32556     68/push 1/imm32/is-atom?:true
32557     68/push 0x11/imm32/alloc-id:fake:payload
32558     89/<- %ecx 4/r32/esp
32559 $test-emit-subx-stmt-primitive-register:initialize-var:
32560     # var var-foo/ecx: (payload var)
32561     68/push 0/imm32/register
32562     68/push 0/imm32/register
32563     68/push 0/imm32/no-stack-offset
32564     68/push 1/imm32/block-depth
32565     51/push-ecx
32566     68/push 0x11/imm32/alloc-id:fake
32567     68/push 0/imm32/name
32568     68/push 0/imm32/name
32569     68/push 0x11/imm32/alloc-id:fake:payload
32570     89/<- %ecx 4/r32/esp
32571 $test-emit-subx-stmt-primitive-register:initialize-var-name:
32572     # var-foo->name = "foo"
32573     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32574     (copy-array Heap "foo" %eax)
32575 $test-emit-subx-stmt-primitive-register:initialize-var-register:
32576     # var-foo->register = "eax"
32577     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32578     (copy-array Heap "eax" %eax)
32579 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
32580     # var operand/ebx: (payload stmt-var)
32581     68/push 0/imm32/is-deref:false
32582     68/push 0/imm32/next
32583     68/push 0/imm32/next
32584     51/push-ecx/var-foo
32585     68/push 0x11/imm32/alloc-id:fake
32586     68/push 0x11/imm32/alloc-id:fake:payload
32587     89/<- %ebx 4/r32/esp
32588 $test-emit-subx-stmt-primitive-register:initialize-stmt:
32589     # var stmt/esi: (addr statement)
32590     53/push-ebx/outputs
32591     68/push 0x11/imm32/alloc-id:fake
32592     68/push 0/imm32/no-inouts
32593     68/push 0/imm32/no-inouts
32594     68/push 0/imm32/operation
32595     68/push 0/imm32/operation
32596     68/push 1/imm32
32597     89/<- %esi 4/r32/esp
32598 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
32599     # stmt->operation = "increment"
32600     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32601     (copy-array Heap "increment" %eax)
32602 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
32603     # var formal-var/ebx: (payload var)
32604     68/push 0/imm32/register
32605     68/push 0/imm32/register
32606     68/push 0/imm32/no-stack-offset
32607     68/push 1/imm32/block-depth
32608     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
32609     68/push 0x11/imm32/alloc-id:fake
32610     68/push 0/imm32/name
32611     68/push 0/imm32/name
32612     68/push 0x11/imm32/alloc-id:fake:payload
32613     89/<- %ebx 4/r32/esp
32614 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
32615     # formal-var->name = "dummy"
32616     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
32617     (copy-array Heap "dummy" %eax)
32618 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
32619     # formal-var->register = "*"
32620     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
32621     (copy-array Heap "*" %eax)  # Any-register
32622 $test-emit-subx-stmt-primitive-register:initialize-var-list:
32623     # var formal-outputs/ebx: (payload list var)
32624     68/push 0/imm32/next
32625     68/push 0/imm32/next
32626     53/push-ebx/formal-var
32627     68/push 0x11/imm32/alloc-id:fake
32628     68/push 0x11/imm32/alloc-id:fake:payload
32629     89/<- %ebx 4/r32/esp
32630 $test-emit-subx-stmt-primitive-register:initialize-primitive:
32631     # var primitives/ebx: (addr primitive)
32632     68/push 0/imm32/next
32633     68/push 0/imm32/next
32634     68/push 0/imm32/no-x32
32635     68/push 0/imm32/no-xm32
32636     68/push 0/imm32/no-disp32
32637     68/push 0/imm32/no-imm8
32638     68/push 0/imm32/no-imm32
32639     68/push 0/imm32/no-r32
32640     68/push 3/imm32/rm32-is-first-output
32641     68/push 0/imm32/subx-name
32642     68/push 0/imm32/subx-name
32643     53/push-ebx/outputs
32644     68/push 0x11/imm32/alloc-id:fake
32645     68/push 0/imm32/no-inouts
32646     68/push 0/imm32/no-inouts
32647     68/push 0/imm32/name
32648     68/push 0/imm32/name
32649     89/<- %ebx 4/r32/esp
32650 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
32651     # primitives->name = "increment"
32652     (copy-array Heap "increment" %ebx)  # Primitive-name
32653 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
32654     # primitives->subx-name = "ff 0/subop/increment"
32655     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
32656     (copy-array Heap "ff 0/subop/increment" %eax)
32657     # convert
32658     c7 0/subop/copy *Curr-block-depth 0/imm32
32659     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
32660     (flush _test-output-buffered-file)
32661 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
32667     # check output
32668     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
32669     # . epilogue
32670     89/<- %esp 5/r32/ebp
32671     5d/pop-to-ebp
32672     c3/return
32673 
32674 test-emit-subx-stmt-select-primitive:
32675     # Select the right primitive between overloads.
32676     #   foo <- increment
32677     # =>
32678     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
32679     #
32680     # There's a variable on the var stack as follows:
32681     #   name: 'foo'
32682     #   type: int
32683     #   register: 'eax'
32684     #
32685     # There's two primitives, as follows:
32686     #   - name: 'increment'
32687     #     out: int/reg
32688     #     value: 'ff 0/subop/increment'
32689     #   - name: 'increment'
32690     #     inout: int/mem
32691     #     value: 'ff 0/subop/increment'
32692     #
32693     # . prologue
32694     55/push-ebp
32695     89/<- %ebp 4/r32/esp
32696     # setup
32697     (clear-stream _test-output-stream)
32698     (clear-stream $_test-output-buffered-file->buffer)
32699 $test-emit-subx-stmt-select-primitive:initialize-type:
32700     # var type/ecx: (payload type-tree) = int
32701     68/push 0/imm32/right:null
32702     68/push 0/imm32/right:null
32703     68/push 0/imm32/left:unused
32704     68/push 1/imm32/value:int
32705     68/push 1/imm32/is-atom?:true
32706     68/push 0x11/imm32/alloc-id:fake:payload
32707     89/<- %ecx 4/r32/esp
32708 $test-emit-subx-stmt-select-primitive:initialize-var:
32709     # var var-foo/ecx: (payload var)
32710     68/push 0/imm32/register
32711     68/push 0/imm32/register
32712     68/push 0/imm32/no-stack-offset
32713     68/push 1/imm32/block-depth
32714     51/push-ecx
32715     68/push 0x11/imm32/alloc-id:fake
32716     68/push 0/imm32/name
32717     68/push 0/imm32/name
32718     68/push 0x11/imm32/alloc-id:fake:payload
32719     89/<- %ecx 4/r32/esp
32720 $test-emit-subx-stmt-select-primitive:initialize-var-name:
32721     # var-foo->name = "foo"
32722     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32723     (copy-array Heap "foo" %eax)
32724 $test-emit-subx-stmt-select-primitive:initialize-var-register:
32725     # var-foo->register = "eax"
32726     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32727     (copy-array Heap "eax" %eax)
32728 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
32729     # var operand/ebx: (payload stmt-var)
32730     68/push 0/imm32/is-deref:false
32731     68/push 0/imm32/next
32732     68/push 0/imm32/next
32733     51/push-ecx/var-foo
32734     68/push 0x11/imm32/alloc-id:fake
32735     68/push 0x11/imm32/alloc-id:fake:payload
32736     89/<- %ebx 4/r32/esp
32737 $test-emit-subx-stmt-select-primitive:initialize-stmt:
32738     # var stmt/esi: (addr statement)
32739     53/push-ebx/outputs
32740     68/push 0x11/imm32/alloc-id:fake
32741     68/push 0/imm32/no-inouts
32742     68/push 0/imm32/no-inouts
32743     68/push 0/imm32/operation
32744     68/push 0/imm32/operation
32745     68/push 1/imm32
32746     89/<- %esi 4/r32/esp
32747 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
32748     # stmt->operation = "increment"
32749     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32750     (copy-array Heap "increment" %eax)
32751 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
32752     # var formal-var/ebx: (payload var)
32753     68/push 0/imm32/register
32754     68/push 0/imm32/register
32755     68/push 0/imm32/no-stack-offset
32756     68/push 1/imm32/block-depth
32757     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
32758     68/push 0x11/imm32/alloc-id:fake
32759     68/push 0/imm32/name
32760     68/push 0/imm32/name
32761     68/push 0x11/imm32/alloc-id:fake:payload
32762     89/<- %ebx 4/r32/esp
32763 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
32764     # formal-var->name = "dummy"
32765     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
32766     (copy-array Heap "dummy" %eax)
32767 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
32768     # formal-var->register = "*"
32769     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
32770     (copy-array Heap "*" %eax)  # Any-register
32771 $test-emit-subx-stmt-select-primitive:initialize-var-list:
32772     # var formal-outputs/ebx: (payload list var)
32773     68/push 0/imm32/next
32774     68/push 0/imm32/next
32775     53/push-ebx/formal-var
32776     68/push 0x11/imm32/alloc-id:fake
32777     68/push 0x11/imm32/alloc-id:fake:payload
32778     89/<- %ebx 4/r32/esp
32779 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
32780     # var primitive2/edi: (payload primitive)
32781     68/push 0/imm32/next
32782     68/push 0/imm32/next
32783     68/push 0/imm32/no-x32
32784     68/push 0/imm32/no-xm32
32785     68/push 0/imm32/no-disp32
32786     68/push 0/imm32/no-imm8
32787     68/push 0/imm32/no-imm32
32788     68/push 0/imm32/no-r32
32789     68/push 3/imm32/rm32-is-first-output
32790     68/push 0/imm32/subx-name
32791     68/push 0/imm32/subx-name
32792     53/push-ebx/outputs
32793     68/push 0x11/imm32/alloc-id:fake
32794     68/push 0/imm32/no-inouts
32795     68/push 0/imm32/no-inouts
32796     68/push 0/imm32/name
32797     68/push 0/imm32/name
32798     68/push 0x11/imm32/alloc-id:fake:payload
32799     89/<- %edi 4/r32/esp
32800 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
32801     # primitives->name = "increment"
32802     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
32803     (copy-array Heap "increment" %eax)
32804 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
32805     # primitives->subx-name = "ff 0/subop/increment"
32806     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
32807     (copy-array Heap "ff 0/subop/increment" %eax)
32808 $test-emit-subx-stmt-select-primitive:initialize-primitive:
32809     # var primitives/ebx: (addr primitive)
32810     57/push-edi
32811     68/push 0x11/imm32/alloc-id:fake
32812     68/push 0/imm32/no-x32
32813     68/push 0/imm32/no-xm32
32814     68/push 0/imm32/no-disp32
32815     68/push 0/imm32/no-imm8
32816     68/push 0/imm32/no-imm32
32817     68/push 0/imm32/no-r32
32818     68/push 1/imm32/rm32-is-first-inout
32819     68/push 0/imm32/subx-name
32820     68/push 0/imm32/subx-name
32821     68/push 0/imm32/no-outputs
32822     68/push 0/imm32/no-outputs
32823     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
32824     68/push 0x11/imm32/alloc-id:fake
32825     68/push 0/imm32/name
32826     68/push 0/imm32/name
32827     89/<- %ebx 4/r32/esp
32828 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
32829     # primitives->name = "increment"
32830     (copy-array Heap "increment" %ebx)  # Primitive-name
32831 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
32832     # primitives->subx-name = "ff 0/subop/increment"
32833     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
32834     (copy-array Heap "ff 0/subop/increment" %eax)
32835     # convert
32836     c7 0/subop/copy *Curr-block-depth 0/imm32
32837     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
32838     (flush _test-output-buffered-file)
32839 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
32845     # check output
32846     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
32847     # . epilogue
32848     89/<- %esp 5/r32/ebp
32849     5d/pop-to-ebp
32850     c3/return
32851 
32852 test-emit-subx-stmt-select-primitive-2:
32853     # Select the right primitive between overloads.
32854     #   increment foo
32855     # =>
32856     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
32857     #
32858     # There's a variable on the var stack as follows:
32859     #   name: 'foo'
32860     #   type: int
32861     #   register: 'eax'
32862     #
32863     # There's two primitives, as follows:
32864     #   - name: 'increment'
32865     #     out: int/reg
32866     #     value: 'ff 0/subop/increment'
32867     #   - name: 'increment'
32868     #     inout: int/mem
32869     #     value: 'ff 0/subop/increment'
32870     #
32871     # . prologue
32872     55/push-ebp
32873     89/<- %ebp 4/r32/esp
32874     # setup
32875     (clear-stream _test-output-stream)
32876     (clear-stream $_test-output-buffered-file->buffer)
32877 $test-emit-subx-stmt-select-primitive-2:initialize-type:
32878     # var type/ecx: (payload type-tree) = int
32879     68/push 0/imm32/right:null
32880     68/push 0/imm32/right:null
32881     68/push 0/imm32/left:unused
32882     68/push 1/imm32/value:int
32883     68/push 1/imm32/is-atom?:true
32884     68/push 0x11/imm32/alloc-id:fake:payload
32885     89/<- %ecx 4/r32/esp
32886 $test-emit-subx-stmt-select-primitive-2:initialize-var:
32887     # var var-foo/ecx: (payload var)
32888     68/push 0/imm32/register
32889     68/push 0/imm32/register
32890     68/push 0/imm32/no-stack-offset
32891     68/push 1/imm32/block-depth
32892     51/push-ecx
32893     68/push 0x11/imm32/alloc-id:fake
32894     68/push 0/imm32/name
32895     68/push 0/imm32/name
32896     68/push 0x11/imm32/alloc-id:fake:payload
32897     89/<- %ecx 4/r32/esp
32898 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
32899     # var-foo->name = "foo"
32900     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
32901     (copy-array Heap "foo" %eax)
32902 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
32903     # var-foo->register = "eax"
32904     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
32905     (copy-array Heap "eax" %eax)
32906 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
32907     # var operand/ebx: (payload stmt-var)
32908     68/push 0/imm32/is-deref:false
32909     68/push 0/imm32/next
32910     68/push 0/imm32/next
32911     51/push-ecx/var-foo
32912     68/push 0x11/imm32/alloc-id:fake
32913     68/push 0x11/imm32/alloc-id:fake:payload
32914     89/<- %ebx 4/r32/esp
32915 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
32916     # var stmt/esi: (addr statement)
32917     68/push 0/imm32/no-outputs
32918     68/push 0/imm32/no-outputs
32919     53/push-ebx/inouts
32920     68/push 0x11/imm32/alloc-id:fake
32921     68/push 0/imm32/operation
32922     68/push 0/imm32/operation
32923     68/push 1/imm32
32924     89/<- %esi 4/r32/esp
32925 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
32926     # stmt->operation = "increment"
32927     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
32928     (copy-array Heap "increment" %eax)
32929 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
32930     # var formal-var/ebx: (payload var)
32931     68/push 0/imm32/register
32932     68/push 0/imm32/register
32933     68/push 0/imm32/no-stack-offset
32934     68/push 1/imm32/block-depth
32935     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
32936     68/push 0x11/imm32/alloc-id:fake
32937     68/push 0/imm32/name
32938     68/push 0/imm32/name
32939     68/push 0x11/imm32/alloc-id:fake:payload
32940     89/<- %ebx 4/r32/esp
32941 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
32942     # formal-var->name = "dummy"
32943     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
32944     (copy-array Heap "dummy" %eax)
32945 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
32946     # formal-var->register = "*"
32947     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
32948     (copy-array Heap "*" %eax)  # Any-register
32949 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
32950     # var formal-outputs/ebx: (payload list stmt-var)
32951     68/push 0/imm32/next
32952     68/push 0/imm32/next
32953     53/push-ebx/formal-var
32954     68/push 0x11/imm32/alloc-id:fake
32955     68/push 0x11/imm32/alloc-id:fake:payload
32956     89/<- %ebx 4/r32/esp
32957 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
32958     # var primitive2/edi: (payload primitive)
32959     68/push 0/imm32/next
32960     68/push 0/imm32/next
32961     68/push 0/imm32/no-x32
32962     68/push 0/imm32/no-xm32
32963     68/push 0/imm32/no-disp32
32964     68/push 0/imm32/no-imm8
32965     68/push 0/imm32/no-imm32
32966     68/push 0/imm32/no-r32
32967     68/push 3/imm32/rm32-is-first-output
32968     68/push 0/imm32/subx-name
32969     68/push 0/imm32/subx-name
32970     53/push-ebx/outputs
32971     68/push 0x11/imm32/alloc-id:fake
32972     68/push 0/imm32/no-inouts
32973     68/push 0/imm32/no-inouts
32974     68/push 0/imm32/name
32975     68/push 0/imm32/name
32976     68/push 0x11/imm32/alloc-id:fake:payload
32977     89/<- %edi 4/r32/esp
32978 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
32979     # primitives->name = "increment"
32980     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
32981     (copy-array Heap "increment" %eax)
32982 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
32983     # primitives->subx-name = "ff 0/subop/increment"
32984     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
32985     (copy-array Heap "ff 0/subop/increment" %eax)
32986 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
32987     # var primitives/ebx: (addr primitive)
32988     57/push-edi
32989     68/push 0x11/imm32/alloc-id:fake
32990     68/push 0/imm32/no-x32
32991     68/push 0/imm32/no-xm32
32992     68/push 0/imm32/no-disp32
32993     68/push 0/imm32/no-imm8
32994     68/push 0/imm32/no-imm32
32995     68/push 0/imm32/no-r32
32996     68/push 1/imm32/rm32-is-first-inout
32997     68/push 0/imm32/subx-name
32998     68/push 0/imm32/subx-name
32999     68/push 0/imm32/no-outputs
33000     68/push 0/imm32/no-outputs
33001     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
33002     68/push 0x11/imm32/alloc-id:fake
33003     68/push 0/imm32/name
33004     68/push 0/imm32/name
33005     89/<- %ebx 4/r32/esp
33006 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
33007     # primitives->name = "increment"
33008     (copy-array Heap "increment" %ebx)  # Primitive-name
33009 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
33010     # primitives->subx-name = "ff 0/subop/increment"
33011     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33012     (copy-array Heap "ff 0/subop/increment" %eax)
33013     # convert
33014     c7 0/subop/copy *Curr-block-depth 0/imm32
33015     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
33016     (flush _test-output-buffered-file)
33017 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33023     # check output
33024     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
33025     # . epilogue
33026     89/<- %esp 5/r32/ebp
33027     5d/pop-to-ebp
33028     c3/return
33029 
33030 test-increment-register:
33031     # Select the right register between overloads.
33032     #   foo <- increment
33033     # =>
33034     #   50/increment-eax
33035     #
33036     # There's a variable on the var stack as follows:
33037     #   name: 'foo'
33038     #   type: int
33039     #   register: 'eax'
33040     #
33041     # Primitives are the global definitions.
33042     #
33043     # . prologue
33044     55/push-ebp
33045     89/<- %ebp 4/r32/esp
33046     # setup
33047     (clear-stream _test-output-stream)
33048     (clear-stream $_test-output-buffered-file->buffer)
33049 $test-increment-register:initialize-type:
33050     # var type/ecx: (payload type-tree) = int
33051     68/push 0/imm32/right:null
33052     68/push 0/imm32/right:null
33053     68/push 0/imm32/left:unused
33054     68/push 1/imm32/value:int
33055     68/push 1/imm32/is-atom?:true
33056     68/push 0x11/imm32/alloc-id:fake:payload
33057     89/<- %ecx 4/r32/esp
33058 $test-increment-register:initialize-var:
33059     # var var-foo/ecx: (payload var)
33060     68/push 0/imm32/register
33061     68/push 0/imm32/register
33062     68/push 0/imm32/no-stack-offset
33063     68/push 1/imm32/block-depth
33064     51/push-ecx
33065     68/push 0x11/imm32/alloc-id:fake
33066     68/push 0/imm32/name
33067     68/push 0/imm32/name
33068     68/push 0x11/imm32/alloc-id:fake:payload
33069     89/<- %ecx 4/r32/esp
33070 $test-increment-register:initialize-var-name:
33071     # var-foo->name = "foo"
33072     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33073     (copy-array Heap "foo" %eax)
33074 $test-increment-register:initialize-var-register:
33075     # var-foo->register = "eax"
33076     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33077     (copy-array Heap "eax" %eax)
33078 $test-increment-register:initialize-stmt-var:
33079     # var operand/ebx: (payload stmt-var)
33080     68/push 0/imm32/is-deref:false
33081     68/push 0/imm32/next
33082     68/push 0/imm32/next
33083     51/push-ecx/var-foo
33084     68/push 0x11/imm32/alloc-id:fake
33085     68/push 0x11/imm32/alloc-id:fake:payload
33086     89/<- %ebx 4/r32/esp
33087 $test-increment-register:initialize-stmt:
33088     # var stmt/esi: (addr statement)
33089     53/push-ebx/outputs
33090     68/push 0x11/imm32/alloc-id:fake
33091     68/push 0/imm32/no-inouts
33092     68/push 0/imm32/no-inouts
33093     68/push 0/imm32/operation
33094     68/push 0/imm32/operation
33095     68/push 1/imm32
33096     89/<- %esi 4/r32/esp
33097 $test-increment-register:initialize-stmt-operation:
33098     # stmt->operation = "increment"
33099     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33100     (copy-array Heap "increment" %eax)
33101     # convert
33102     c7 0/subop/copy *Curr-block-depth 0/imm32
33103     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33104     (flush _test-output-buffered-file)
33105 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33111     # check output
33112     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
33113     # . epilogue
33114     89/<- %esp 5/r32/ebp
33115     5d/pop-to-ebp
33116     c3/return
33117 
33118 test-add-reg-to-reg:
33119     #   var1/reg <- add var2/reg
33120     # =>
33121     #   01/add-to %var1 var2
33122     #
33123     # . prologue
33124     55/push-ebp
33125     89/<- %ebp 4/r32/esp
33126     # setup
33127     (clear-stream _test-output-stream)
33128     (clear-stream $_test-output-buffered-file->buffer)
33129 $test-add-reg-to-reg:initialize-type:
33130     # var type/ecx: (payload type-tree) = int
33131     68/push 0/imm32/right:null
33132     68/push 0/imm32/right:null
33133     68/push 0/imm32/left:unused
33134     68/push 1/imm32/value:int
33135     68/push 1/imm32/is-atom?:true
33136     68/push 0x11/imm32/alloc-id:fake:payload
33137     89/<- %ecx 4/r32/esp
33138 $test-add-reg-to-reg:initialize-var1:
33139     # var var1/ecx: (payload var)
33140     68/push 0/imm32/register
33141     68/push 0/imm32/register
33142     68/push 0/imm32/no-stack-offset
33143     68/push 1/imm32/block-depth
33144     51/push-ecx
33145     68/push 0x11/imm32/alloc-id:fake
33146     68/push 0/imm32/name
33147     68/push 0/imm32/name
33148     68/push 0x11/imm32/alloc-id:fake:payload
33149     89/<- %ecx 4/r32/esp
33150 $test-add-reg-to-reg:initialize-var1-name:
33151     # var1->name = "var1"
33152     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33153     (copy-array Heap "var1" %eax)
33154 $test-add-reg-to-reg:initialize-var1-register:
33155     # var1->register = "eax"
33156     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33157     (copy-array Heap "eax" %eax)
33158 $test-add-reg-to-reg:initialize-var2:
33159     # var var2/edx: (payload var)
33160     68/push 0/imm32/register
33161     68/push 0/imm32/register
33162     68/push 0/imm32/no-stack-offset
33163     68/push 1/imm32/block-depth
33164     ff 6/subop/push *(ecx+0x10)
33165     68/push 0x11/imm32/alloc-id:fake
33166     68/push 0/imm32/name
33167     68/push 0/imm32/name
33168     68/push 0x11/imm32/alloc-id:fake:payload
33169     89/<- %edx 4/r32/esp
33170 $test-add-reg-to-reg:initialize-var2-name:
33171     # var2->name = "var2"
33172     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33173     (copy-array Heap "var2" %eax)
33174 $test-add-reg-to-reg:initialize-var2-register:
33175     # var2->register = "ecx"
33176     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
33177     (copy-array Heap "ecx" %eax)
33178 $test-add-reg-to-reg:initialize-inouts:
33179     # var inouts/esi: (payload stmt-var) = [var2]
33180     68/push 0/imm32/is-deref:false
33181     68/push 0/imm32/next
33182     68/push 0/imm32/next
33183     52/push-edx/var2
33184     68/push 0x11/imm32/alloc-id:fake
33185     68/push 0x11/imm32/alloc-id:fake:payload
33186     89/<- %esi 4/r32/esp
33187 $test-add-reg-to-reg:initialize-outputs:
33188     # var outputs/edi: (payload stmt-var) = [var1]
33189     68/push 0/imm32/is-deref:false
33190     68/push 0/imm32/next
33191     68/push 0/imm32/next
33192     51/push-ecx/var1
33193     68/push 0x11/imm32/alloc-id:fake
33194     68/push 0x11/imm32/alloc-id:fake:payload
33195     89/<- %edi 4/r32/esp
33196 $test-add-reg-to-reg:initialize-stmt:
33197     # var stmt/esi: (addr statement)
33198     68/push 0/imm32/next
33199     68/push 0/imm32/next
33200     57/push-edi/outputs
33201     68/push 0x11/imm32/alloc-id:fake
33202     56/push-esi/inouts
33203     68/push 0x11/imm32/alloc-id:fake
33204     68/push 0/imm32/operation
33205     68/push 0/imm32/operation
33206     68/push 1/imm32/tag:stmt1
33207     89/<- %esi 4/r32/esp
33208 $test-add-reg-to-reg:initialize-stmt-operation:
33209     # stmt->operation = "add"
33210     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33211     (copy-array Heap "add" %eax)
33212     # convert
33213     c7 0/subop/copy *Curr-block-depth 0/imm32
33214     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33215     (flush _test-output-buffered-file)
33216 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33222     # check output
33223     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
33224     # . epilogue
33225     89/<- %esp 5/r32/ebp
33226     5d/pop-to-ebp
33227     c3/return
33228 
33229 test-add-reg-to-mem:
33230     #   add-to var1 var2/reg
33231     # =>
33232     #   01/add-to *(ebp+__) var2
33233     #
33234     # . prologue
33235     55/push-ebp
33236     89/<- %ebp 4/r32/esp
33237     # setup
33238     (clear-stream _test-output-stream)
33239     (clear-stream $_test-output-buffered-file->buffer)
33240 $test-add-reg-to-mem:initialize-type:
33241     # var type/ecx: (payload type-tree) = int
33242     68/push 0/imm32/right:null
33243     68/push 0/imm32/right:null
33244     68/push 0/imm32/left:unused
33245     68/push 1/imm32/value:int
33246     68/push 1/imm32/is-atom?:true
33247     68/push 0x11/imm32/alloc-id:fake:payload
33248     89/<- %ecx 4/r32/esp
33249 $test-add-reg-to-mem:initialize-var1:
33250     # var var1/ecx: (payload var)
33251     68/push 0/imm32/register
33252     68/push 0/imm32/register
33253     68/push 8/imm32/stack-offset
33254     68/push 1/imm32/block-depth
33255     51/push-ecx
33256     68/push 0x11/imm32/alloc-id:fake
33257     68/push 0/imm32/name
33258     68/push 0/imm32/name
33259     68/push 0x11/imm32/alloc-id:fake:payload
33260     89/<- %ecx 4/r32/esp
33261 $test-add-reg-to-mem:initialize-var1-name:
33262     # var1->name = "var1"
33263     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33264     (copy-array Heap "var1" %eax)
33265 $test-add-reg-to-mem:initialize-var2:
33266     # var var2/edx: (payload var)
33267     68/push 0/imm32/register
33268     68/push 0/imm32/register
33269     68/push 0/imm32/no-stack-offset
33270     68/push 1/imm32/block-depth
33271     ff 6/subop/push *(ecx+0x10)
33272     68/push 0x11/imm32/alloc-id:fake
33273     68/push 0/imm32/name
33274     68/push 0/imm32/name
33275     68/push 0x11/imm32/alloc-id:fake:payload
33276     89/<- %edx 4/r32/esp
33277 $test-add-reg-to-mem:initialize-var2-name:
33278     # var2->name = "var2"
33279     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33280     (copy-array Heap "var2" %eax)
33281 $test-add-reg-to-mem:initialize-var2-register:
33282     # var2->register = "ecx"
33283     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
33284     (copy-array Heap "ecx" %eax)
33285 $test-add-reg-to-mem:initialize-inouts:
33286     # var inouts/esi: (payload stmt-var) = [var2]
33287     68/push 0/imm32/is-deref:false
33288     68/push 0/imm32/next
33289     68/push 0/imm32/next
33290     52/push-edx/var2
33291     68/push 0x11/imm32/alloc-id:fake
33292     68/push 0x11/imm32/alloc-id:fake:payload
33293     89/<- %esi 4/r32/esp
33294     # inouts = [var1, var2]
33295     68/push 0/imm32/is-deref:false
33296     56/push-esi/next
33297     68/push 0x11/imm32/alloc-id:fake
33298     51/push-ecx/var1
33299     68/push 0x11/imm32/alloc-id:fake
33300     68/push 0x11/imm32/alloc-id:fake:payload
33301     89/<- %esi 4/r32/esp
33302 $test-add-reg-to-mem:initialize-stmt:
33303     # var stmt/esi: (addr statement)
33304     68/push 0/imm32/next
33305     68/push 0/imm32/next
33306     68/push 0/imm32/outputs
33307     68/push 0/imm32/outputs
33308     56/push-esi/inouts
33309     68/push 0x11/imm32/alloc-id:fake
33310     68/push 0/imm32/operation
33311     68/push 0/imm32/operation
33312     68/push 1/imm32/tag:stmt1
33313     89/<- %esi 4/r32/esp
33314 $test-add-reg-to-mem:initialize-stmt-operation:
33315     # stmt->operation = "add-to"
33316     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33317     (copy-array Heap "add-to" %eax)
33318     # convert
33319     c7 0/subop/copy *Curr-block-depth 0/imm32
33320     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33321     (flush _test-output-buffered-file)
33322 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33328     # check output
33329     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
33330     # . epilogue
33331     89/<- %esp 5/r32/ebp
33332     5d/pop-to-ebp
33333     c3/return
33334 
33335 test-add-mem-to-reg:
33336     #   var1/reg <- add var2
33337     # =>
33338     #   03/add *(ebp+__) var1
33339     #
33340     # . prologue
33341     55/push-ebp
33342     89/<- %ebp 4/r32/esp
33343     # setup
33344     (clear-stream _test-output-stream)
33345     (clear-stream $_test-output-buffered-file->buffer)
33346 $test-add-mem-to-reg:initialize-type:
33347     # var type/ecx: (payload type-tree) = int
33348     68/push 0/imm32/right:null
33349     68/push 0/imm32/right:null
33350     68/push 0/imm32/left:unused
33351     68/push 1/imm32/value:int
33352     68/push 1/imm32/is-atom?:true
33353     68/push 0x11/imm32/alloc-id:fake:payload
33354     89/<- %ecx 4/r32/esp
33355 $test-add-mem-to-reg:initialize-var:
33356     # var var1/ecx: (payload var)
33357     68/push 0/imm32/register
33358     68/push 0/imm32/register
33359     68/push 0/imm32/no-stack-offset
33360     68/push 1/imm32/block-depth
33361     51/push-ecx
33362     68/push 0x11/imm32/alloc-id:fake
33363     68/push 0/imm32/name
33364     68/push 0/imm32/name
33365     68/push 0x11/imm32/alloc-id:fake:payload
33366     89/<- %ecx 4/r32/esp
33367 $test-add-mem-to-reg:initialize-var-name:
33368     # var1->name = "foo"
33369     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33370     (copy-array Heap "var1" %eax)
33371 $test-add-mem-to-reg:initialize-var-register:
33372     # var1->register = "eax"
33373     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33374     (copy-array Heap "eax" %eax)
33375 $test-add-mem-to-reg:initialize-var2:
33376     # var var2/edx: (payload var)
33377     68/push 0/imm32/register
33378     68/push 0/imm32/register
33379     68/push 8/imm32/stack-offset
33380     68/push 1/imm32/block-depth
33381     ff 6/subop/push *(ecx+0x10)
33382     68/push 0x11/imm32/alloc-id:fake
33383     68/push 0/imm32/name
33384     68/push 0/imm32/name
33385     68/push 0x11/imm32/alloc-id:fake:payload
33386     89/<- %edx 4/r32/esp
33387 $test-add-mem-to-reg:initialize-var2-name:
33388     # var2->name = "var2"
33389     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33390     (copy-array Heap "var2" %eax)
33391 $test-add-mem-to-reg:initialize-inouts:
33392     # var inouts/esi: (payload stmt-var) = [var2]
33393     68/push 0/imm32/is-deref:false
33394     68/push 0/imm32/next
33395     68/push 0/imm32/next
33396     52/push-edx/var2
33397     68/push 0x11/imm32/alloc-id:fake
33398     68/push 0x11/imm32/alloc-id:fake:payload
33399     89/<- %esi 4/r32/esp
33400 $test-add-mem-to-reg:initialize-outputs:
33401     # var outputs/edi: (payload stmt-var) = [var1]
33402     68/push 0/imm32/is-deref:false
33403     68/push 0/imm32/next
33404     68/push 0/imm32/next
33405     51/push-ecx/var1
33406     68/push 0x11/imm32/alloc-id:fake
33407     68/push 0x11/imm32/alloc-id:fake:payload
33408     89/<- %edi 4/r32/esp
33409 $test-add-mem-to-reg:initialize-stmt:
33410     # var stmt/esi: (addr statement)
33411     68/push 0/imm32/next
33412     68/push 0/imm32/next
33413     57/push-edi/outputs
33414     68/push 0x11/imm32/alloc-id:fake
33415     56/push-esi/inouts
33416     68/push 0x11/imm32/alloc-id:fake
33417     68/push 0/imm32/operation
33418     68/push 0/imm32/operation
33419     68/push 1/imm32/tag:stmt1
33420     89/<- %esi 4/r32/esp
33421 $test-add-mem-to-reg:initialize-stmt-operation:
33422     # stmt->operation = "add"
33423     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33424     (copy-array Heap "add" %eax)
33425     # convert
33426     c7 0/subop/copy *Curr-block-depth 0/imm32
33427     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33428     (flush _test-output-buffered-file)
33429 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33435     # check output
33436     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
33437     # . epilogue
33438     89/<- %esp 5/r32/ebp
33439     5d/pop-to-ebp
33440     c3/return
33441 
33442 test-add-literal-to-eax:
33443     #   var1/eax <- add 0x34
33444     # =>
33445     #   05/add-to-eax 0x34/imm32
33446     #
33447     # . prologue
33448     55/push-ebp
33449     89/<- %ebp 4/r32/esp
33450     # setup
33451     (clear-stream _test-output-stream)
33452     (clear-stream $_test-output-buffered-file->buffer)
33453 $test-add-literal-to-eax:initialize-var-type:
33454     # var type/ecx: (payload type-tree) = int
33455     68/push 0/imm32/right:null
33456     68/push 0/imm32/right:null
33457     68/push 0/imm32/left:unused
33458     68/push 1/imm32/value:int
33459     68/push 1/imm32/is-atom?:true
33460     68/push 0x11/imm32/alloc-id:fake:payload
33461     89/<- %ecx 4/r32/esp
33462 $test-add-literal-to-eax:initialize-var:
33463     # var v/ecx: (payload var)
33464     68/push 0/imm32/register
33465     68/push 0/imm32/register
33466     68/push 0/imm32/no-stack-offset
33467     68/push 1/imm32/block-depth
33468     51/push-ecx
33469     68/push 0x11/imm32/alloc-id:fake
33470     68/push 0/imm32/name
33471     68/push 0/imm32/name
33472     68/push 0x11/imm32/alloc-id:fake:payload
33473     89/<- %ecx 4/r32/esp
33474 $test-add-literal-to-eax:initialize-var-name:
33475     # v->name = "v"
33476     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33477     (copy-array Heap "v" %eax)
33478 $test-add-literal-to-eax:initialize-var-register:
33479     # v->register = "eax"
33480     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33481     (copy-array Heap "eax" %eax)
33482 $test-add-literal-to-eax:initialize-literal-type:
33483     # var type/edx: (payload type-tree) = literal
33484     68/push 0/imm32/right:null
33485     68/push 0/imm32/right:null
33486     68/push 0/imm32/left:unused
33487     68/push 0/imm32/value:literal
33488     68/push 1/imm32/is-atom?:true
33489     68/push 0x11/imm32/alloc-id:fake:payload
33490     89/<- %edx 4/r32/esp
33491 $test-add-literal-to-eax:initialize-literal:
33492     # var l/edx: (payload var)
33493     68/push 0/imm32/register
33494     68/push 0/imm32/register
33495     68/push 0/imm32/no-stack-offset
33496     68/push 1/imm32/block-depth
33497     52/push-edx
33498     68/push 0x11/imm32/alloc-id:fake
33499     68/push 0/imm32/name
33500     68/push 0/imm32/name
33501     68/push 0x11/imm32/alloc-id:fake:payload
33502     89/<- %edx 4/r32/esp
33503 $test-add-literal-to-eax:initialize-literal-value:
33504     # l->name = "0x34"
33505     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33506     (copy-array Heap "0x34" %eax)
33507 $test-add-literal-to-eax:initialize-inouts:
33508     # var inouts/esi: (payload stmt-var) = [l]
33509     68/push 0/imm32/is-deref:false
33510     68/push 0/imm32/next
33511     68/push 0/imm32/next
33512     52/push-edx/l
33513     68/push 0x11/imm32/alloc-id:fake
33514     68/push 0x11/imm32/alloc-id:fake:payload
33515     89/<- %esi 4/r32/esp
33516 $test-add-literal-to-eax:initialize-outputs:
33517     # var outputs/edi: (payload stmt-var) = [v]
33518     68/push 0/imm32/is-deref:false
33519     68/push 0/imm32/next
33520     68/push 0/imm32/next
33521     51/push-ecx/v
33522     68/push 0x11/imm32/alloc-id:fake
33523     68/push 0x11/imm32/alloc-id:fake:payload
33524     89/<- %edi 4/r32/esp
33525 $test-add-literal-to-eax:initialize-stmt:
33526     # var stmt/esi: (addr statement)
33527     68/push 0/imm32/next
33528     68/push 0/imm32/next
33529     57/push-edi/outputs
33530     68/push 0x11/imm32/alloc-id:fake
33531     56/push-esi/inouts
33532     68/push 0x11/imm32/alloc-id:fake
33533     68/push 0/imm32/operation
33534     68/push 0/imm32/operation
33535     68/push 1/imm32/tag:stmt1
33536     89/<- %esi 4/r32/esp
33537 $test-add-literal-to-eax:initialize-stmt-operation:
33538     # stmt->operation = "add"
33539     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33540     (copy-array Heap "add" %eax)
33541     # convert
33542     c7 0/subop/copy *Curr-block-depth 0/imm32
33543     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33544     (flush _test-output-buffered-file)
33545 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33551     # check output
33552     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
33553     # . epilogue
33554     89/<- %esp 5/r32/ebp
33555     5d/pop-to-ebp
33556     c3/return
33557 
33558 test-add-literal-to-reg:
33559     #   var1/ecx <- add 0x34
33560     # =>
33561     #   81 0/subop/add %ecx 0x34/imm32
33562     #
33563     # . prologue
33564     55/push-ebp
33565     89/<- %ebp 4/r32/esp
33566     # setup
33567     (clear-stream _test-output-stream)
33568     (clear-stream $_test-output-buffered-file->buffer)
33569 $test-add-literal-to-reg:initialize-var-type:
33570     # var type/ecx: (payload type-tree) = int
33571     68/push 0/imm32/right:null
33572     68/push 0/imm32/right:null
33573     68/push 0/imm32/left:unused
33574     68/push 1/imm32/value:int
33575     68/push 1/imm32/is-atom?:true
33576     68/push 0x11/imm32/alloc-id:fake:payload
33577     89/<- %ecx 4/r32/esp
33578 $test-add-literal-to-reg:initialize-var:
33579     # var v/ecx: (payload var)
33580     68/push 0/imm32/register
33581     68/push 0/imm32/register
33582     68/push 0/imm32/no-stack-offset
33583     68/push 1/imm32/block-depth
33584     51/push-ecx
33585     68/push 0x11/imm32/alloc-id:fake
33586     68/push 0/imm32/name
33587     68/push 0/imm32/name
33588     68/push 0x11/imm32/alloc-id:fake:payload
33589     89/<- %ecx 4/r32/esp
33590 $test-add-literal-to-reg:initialize-var-name:
33591     # v->name = "v"
33592     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33593     (copy-array Heap "v" %eax)
33594 $test-add-literal-to-reg:initialize-var-register:
33595     # v->register = "ecx"
33596     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33597     (copy-array Heap "ecx" %eax)
33598 $test-add-literal-to-reg:initialize-literal-type:
33599     # var type/edx: (payload type-tree) = literal
33600     68/push 0/imm32/right:null
33601     68/push 0/imm32/right:null
33602     68/push 0/imm32/left:unused
33603     68/push 0/imm32/value:literal
33604     68/push 1/imm32/is-atom?:true
33605     68/push 0x11/imm32/alloc-id:fake:payload
33606     89/<- %edx 4/r32/esp
33607 $test-add-literal-to-reg:initialize-literal:
33608     # var l/edx: (payload var)
33609     68/push 0/imm32/register
33610     68/push 0/imm32/register
33611     68/push 0/imm32/no-stack-offset
33612     68/push 1/imm32/block-depth
33613     52/push-edx
33614     68/push 0x11/imm32/alloc-id:fake
33615     68/push 0/imm32/name
33616     68/push 0/imm32/name
33617     68/push 0x11/imm32/alloc-id:fake:payload
33618     89/<- %edx 4/r32/esp
33619 $test-add-literal-to-reg:initialize-literal-value:
33620     # l->name = "0x34"
33621     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33622     (copy-array Heap "0x34" %eax)
33623 $test-add-literal-to-reg:initialize-inouts:
33624     # var inouts/esi: (payload stmt-var) = [l]
33625     68/push 0/imm32/is-deref:false
33626     68/push 0/imm32/next
33627     68/push 0/imm32/next
33628     52/push-edx/l
33629     68/push 0x11/imm32/alloc-id:fake
33630     68/push 0x11/imm32/alloc-id:fake:payload
33631     89/<- %esi 4/r32/esp
33632 $test-add-literal-to-reg:initialize-outputs:
33633     # var outputs/edi: (payload stmt-var) = [v]
33634     68/push 0/imm32/is-deref:false
33635     68/push 0/imm32/next
33636     68/push 0/imm32/next
33637     51/push-ecx/v
33638     68/push 0x11/imm32/alloc-id:fake
33639     68/push 0x11/imm32/alloc-id:fake:payload
33640     89/<- %edi 4/r32/esp
33641 $test-add-literal-to-reg:initialize-stmt:
33642     # var stmt/esi: (addr statement)
33643     68/push 0/imm32/next
33644     68/push 0/imm32/next
33645     57/push-edi/outputs
33646     68/push 0x11/imm32/alloc-id:fake
33647     56/push-esi/inouts
33648     68/push 0x11/imm32/alloc-id:fake
33649     68/push 0/imm32/operation
33650     68/push 0/imm32/operation
33651     68/push 1/imm32/tag:stmt1
33652     89/<- %esi 4/r32/esp
33653 $test-add-literal-to-reg:initialize-stmt-operation:
33654     # stmt->operation = "add"
33655     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33656     (copy-array Heap "add" %eax)
33657     # convert
33658     c7 0/subop/copy *Curr-block-depth 0/imm32
33659     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33660     (flush _test-output-buffered-file)
33661 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33667     # check output
33668     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
33669     # . epilogue
33670     89/<- %esp 5/r32/ebp
33671     5d/pop-to-ebp
33672     c3/return
33673 
33674 test-add-literal-to-mem:
33675     #   add-to var1, 0x34
33676     # =>
33677     #   81 0/subop/add %eax 0x34/imm32
33678     #
33679     # . prologue
33680     55/push-ebp
33681     89/<- %ebp 4/r32/esp
33682     # setup
33683     (clear-stream _test-output-stream)
33684     (clear-stream $_test-output-buffered-file->buffer)
33685 $test-add-literal-to-mem:initialize-type:
33686     # var type/ecx: (payload type-tree) = int
33687     68/push 0/imm32/right:null
33688     68/push 0/imm32/right:null
33689     68/push 0/imm32/left:unused
33690     68/push 1/imm32/value:int
33691     68/push 1/imm32/is-atom?:true
33692     68/push 0x11/imm32/alloc-id:fake:payload
33693     89/<- %ecx 4/r32/esp
33694 $test-add-literal-to-mem:initialize-var1:
33695     # var var1/ecx: (payload var)
33696     68/push 0/imm32/register
33697     68/push 0/imm32/register
33698     68/push 8/imm32/stack-offset
33699     68/push 1/imm32/block-depth
33700     51/push-ecx
33701     68/push 0x11/imm32/alloc-id:fake
33702     68/push 0/imm32/name
33703     68/push 0/imm32/name
33704     68/push 0x11/imm32/alloc-id:fake:payload
33705     89/<- %ecx 4/r32/esp
33706 $test-add-literal-to-mem:initialize-var1-name:
33707     # var1->name = "var1"
33708     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33709     (copy-array Heap "var1" %eax)
33710 $test-add-literal-to-mem:initialize-literal-type:
33711     # var type/edx: (payload type-tree) = literal
33712     68/push 0/imm32/right:null
33713     68/push 0/imm32/right:null
33714     68/push 0/imm32/left:unused
33715     68/push 0/imm32/value:literal
33716     68/push 1/imm32/is-atom?:true
33717     68/push 0x11/imm32/alloc-id:fake:payload
33718     89/<- %edx 4/r32/esp
33719 $test-add-literal-to-mem:initialize-literal:
33720     # var l/edx: (payload var)
33721     68/push 0/imm32/register
33722     68/push 0/imm32/register
33723     68/push 0/imm32/no-stack-offset
33724     68/push 1/imm32/block-depth
33725     52/push-edx
33726     68/push 0x11/imm32/alloc-id:fake
33727     68/push 0/imm32/name
33728     68/push 0/imm32/name
33729     68/push 0x11/imm32/alloc-id:fake:payload
33730     89/<- %edx 4/r32/esp
33731 $test-add-literal-to-mem:initialize-literal-value:
33732     # l->name = "0x34"
33733     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33734     (copy-array Heap "0x34" %eax)
33735 $test-add-literal-to-mem:initialize-inouts:
33736     # var inouts/esi: (payload stmt-var) = [l]
33737     68/push 0/imm32/is-deref:false
33738     68/push 0/imm32/next
33739     68/push 0/imm32/next
33740     52/push-edx/l
33741     68/push 0x11/imm32/alloc-id:fake
33742     68/push 0x11/imm32/alloc-id:fake:payload
33743     89/<- %esi 4/r32/esp
33744     # var inouts = (handle stmt-var) = [var1, var2]
33745     68/push 0/imm32/is-deref:false
33746     56/push-esi/next
33747     68/push 0x11/imm32/alloc-id:fake
33748     51/push-ecx/var1
33749     68/push 0x11/imm32/alloc-id:fake
33750     68/push 0x11/imm32/alloc-id:fake:payload
33751     89/<- %esi 4/r32/esp
33752 $test-add-literal-to-mem:initialize-stmt:
33753     # var stmt/esi: (addr statement)
33754     68/push 0/imm32/next
33755     68/push 0/imm32/next
33756     68/push 0/imm32/outputs
33757     68/push 0/imm32/outputs
33758     56/push-esi/inouts
33759     68/push 0x11/imm32/alloc-id:fake
33760     68/push 0/imm32/operation
33761     68/push 0/imm32/operation
33762     68/push 1/imm32/tag:stmt1
33763     89/<- %esi 4/r32/esp
33764 $test-add-literal-to-mem:initialize-stmt-operation:
33765     # stmt->operation = "add-to"
33766     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33767     (copy-array Heap "add-to" %eax)
33768     # convert
33769     c7 0/subop/copy *Curr-block-depth 0/imm32
33770     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33771     (flush _test-output-buffered-file)
33772 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33778     # check output
33779     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
33780     # . epilogue
33781     89/<- %esp 5/r32/ebp
33782     5d/pop-to-ebp
33783     c3/return
33784 
33785 test-shift-reg-by-literal:
33786     #   var1/ecx <- shift-left 2
33787     # =>
33788     #   c1/shift 4/subop/left %ecx 2/imm8
33789     #
33790     # . prologue
33791     55/push-ebp
33792     89/<- %ebp 4/r32/esp
33793     # setup
33794     (clear-stream _test-output-stream)
33795     (clear-stream $_test-output-buffered-file->buffer)
33796 $test-shift-reg-by-literal:initialize-var-type:
33797     # var type/ecx: (payload type-tree) = int
33798     68/push 0/imm32/right:null
33799     68/push 0/imm32/right:null
33800     68/push 0/imm32/left:unused
33801     68/push 1/imm32/value:int
33802     68/push 1/imm32/is-atom?:true
33803     68/push 0x11/imm32/alloc-id:fake:payload
33804     89/<- %ecx 4/r32/esp
33805 $test-shift-reg-by-literal:initialize-var:
33806     # var v/ecx: (payload var)
33807     68/push 0/imm32/register
33808     68/push 0/imm32/register
33809     68/push 0/imm32/no-stack-offset
33810     68/push 1/imm32/block-depth
33811     51/push-ecx
33812     68/push 0x11/imm32/alloc-id:fake
33813     68/push 0/imm32/name
33814     68/push 0/imm32/name
33815     68/push 0x11/imm32/alloc-id:fake:payload
33816     89/<- %ecx 4/r32/esp
33817 $test-shift-reg-by-literal:initialize-var-name:
33818     # v->name = "v"
33819     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33820     (copy-array Heap "v" %eax)
33821 $test-shift-reg-by-literal:initialize-var-register:
33822     # v->register = "ecx"
33823     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33824     (copy-array Heap "ecx" %eax)
33825 $test-shift-reg-by-literal:initialize-literal-type:
33826     # var type/edx: (payload type-tree) = literal
33827     68/push 0/imm32/right:null
33828     68/push 0/imm32/right:null
33829     68/push 0/imm32/left:unused
33830     68/push 0/imm32/value:literal
33831     68/push 1/imm32/is-atom?:true
33832     68/push 0x11/imm32/alloc-id:fake:payload
33833     89/<- %edx 4/r32/esp
33834 $test-shift-reg-by-literal:initialize-literal:
33835     # var l/edx: (payload var)
33836     68/push 0/imm32/register
33837     68/push 0/imm32/register
33838     68/push 0/imm32/no-stack-offset
33839     68/push 1/imm32/block-depth
33840     52/push-edx
33841     68/push 0x11/imm32/alloc-id:fake
33842     68/push 0/imm32/name
33843     68/push 0/imm32/name
33844     68/push 0x11/imm32/alloc-id:fake:payload
33845     89/<- %edx 4/r32/esp
33846 $test-shift-reg-by-literal:initialize-literal-value:
33847     # l->name = "2"
33848     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33849     (copy-array Heap "2" %eax)
33850 $test-shift-reg-by-literal:initialize-inouts:
33851     # var inouts/esi: (payload stmt-var) = [l]
33852     68/push 0/imm32/is-deref:false
33853     68/push 0/imm32/next
33854     68/push 0/imm32/next
33855     52/push-edx/l
33856     68/push 0x11/imm32/alloc-id:fake
33857     68/push 0x11/imm32/alloc-id:fake:payload
33858     89/<- %esi 4/r32/esp
33859 $test-shift-reg-by-literal:initialize-outputs:
33860     # var outputs/edi: (payload stmt-var) = [v]
33861     68/push 0/imm32/is-deref:false
33862     68/push 0/imm32/next
33863     68/push 0/imm32/next
33864     51/push-ecx/v
33865     68/push 0x11/imm32/alloc-id:fake
33866     68/push 0x11/imm32/alloc-id:fake:payload
33867     89/<- %edi 4/r32/esp
33868 $test-shift-reg-by-literal:initialize-stmt:
33869     # var stmt/esi: (addr statement)
33870     68/push 0/imm32/next
33871     68/push 0/imm32/next
33872     57/push-edi/outputs
33873     68/push 0x11/imm32/alloc-id:fake
33874     56/push-esi/inouts
33875     68/push 0x11/imm32/alloc-id:fake
33876     68/push 0/imm32/operation
33877     68/push 0/imm32/operation
33878     68/push 1/imm32/tag:stmt1
33879     89/<- %esi 4/r32/esp
33880 $test-shift-reg-by-literal:initialize-stmt-operation:
33881     # stmt->operation = "shift-left"
33882     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33883     (copy-array Heap "shift-left" %eax)
33884     # convert
33885     c7 0/subop/copy *Curr-block-depth 0/imm32
33886     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33887     (flush _test-output-buffered-file)
33888 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33894     # check output
33895     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
33896     # . epilogue
33897     89/<- %esp 5/r32/ebp
33898     5d/pop-to-ebp
33899     c3/return
33900 
33901 test-shift-mem-by-literal:
33902     #   shift-left var 3
33903     # =>
33904     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
33905     #
33906     # . prologue
33907     55/push-ebp
33908     89/<- %ebp 4/r32/esp
33909     # setup
33910     (clear-stream _test-output-stream)
33911     (clear-stream $_test-output-buffered-file->buffer)
33912 $test-shift-mem-by-literal:initialize-type:
33913     # var type/ecx: (payload type-tree) = int
33914     68/push 0/imm32/right:null
33915     68/push 0/imm32/right:null
33916     68/push 0/imm32/left:unused
33917     68/push 1/imm32/value:int
33918     68/push 1/imm32/is-atom?:true
33919     68/push 0x11/imm32/alloc-id:fake:payload
33920     89/<- %ecx 4/r32/esp
33921 $test-shift-mem-by-literal:initialize-var1:
33922     # var var1/ecx: (payload var)
33923     68/push 0/imm32/register
33924     68/push 0/imm32/register
33925     68/push 8/imm32/stack-offset
33926     68/push 1/imm32/block-depth
33927     51/push-ecx
33928     68/push 0x11/imm32/alloc-id:fake
33929     68/push 0/imm32/name
33930     68/push 0/imm32/name
33931     68/push 0x11/imm32/alloc-id:fake:payload
33932     89/<- %ecx 4/r32/esp
33933 $test-shift-mem-by-literal:initialize-var1-name:
33934     # var1->name = "var1"
33935     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33936     (copy-array Heap "var1" %eax)
33937 $test-shift-mem-by-literal:initialize-literal-type:
33938     # var type/edx: (payload type-tree) = literal
33939     68/push 0/imm32/right:null
33940     68/push 0/imm32/right:null
33941     68/push 0/imm32/left:unused
33942     68/push 0/imm32/value:literal
33943     68/push 1/imm32/is-atom?:true
33944     68/push 0x11/imm32/alloc-id:fake:payload
33945     89/<- %edx 4/r32/esp
33946 $test-shift-mem-by-literal:initialize-literal:
33947     # var l/edx: (payload var)
33948     68/push 0/imm32/register
33949     68/push 0/imm32/register
33950     68/push 0/imm32/no-stack-offset
33951     68/push 1/imm32/block-depth
33952     52/push-edx
33953     68/push 0x11/imm32/alloc-id:fake
33954     68/push 0/imm32/name
33955     68/push 0/imm32/name
33956     68/push 0x11/imm32/alloc-id:fake:payload
33957     89/<- %edx 4/r32/esp
33958 $test-shift-mem-by-literal:initialize-literal-value:
33959     # l->name = "3"
33960     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
33961     (copy-array Heap "3" %eax)
33962 $test-shift-mem-by-literal:initialize-inouts:
33963     # var inouts/esi: (payload stmt-var) = [l]
33964     68/push 0/imm32/is-deref:false
33965     68/push 0/imm32/next
33966     68/push 0/imm32/next
33967     52/push-edx/l
33968     68/push 0x11/imm32/alloc-id:fake
33969     68/push 0x11/imm32/alloc-id:fake:payload
33970     89/<- %esi 4/r32/esp
33971     # var inouts = (handle stmt-var) = [var1, var2]
33972     68/push 0/imm32/is-deref:false
33973     56/push-esi/next
33974     68/push 0x11/imm32/alloc-id:fake
33975     51/push-ecx/var1
33976     68/push 0x11/imm32/alloc-id:fake
33977     68/push 0x11/imm32/alloc-id:fake:payload
33978     89/<- %esi 4/r32/esp
33979 $test-shift-mem-by-literal:initialize-stmt:
33980     # var stmt/esi: (addr statement)
33981     68/push 0/imm32/next
33982     68/push 0/imm32/next
33983     68/push 0/imm32/outputs
33984     68/push 0/imm32/outputs
33985     56/push-esi/inouts
33986     68/push 0x11/imm32/alloc-id:fake
33987     68/push 0/imm32/operation
33988     68/push 0/imm32/operation
33989     68/push 1/imm32/tag:stmt1
33990     89/<- %esi 4/r32/esp
33991 $test-shift-mem-by-literal:initialize-stmt-operation:
33992     # stmt->operation = "shift-left"
33993     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33994     (copy-array Heap "shift-left" %eax)
33995     # convert
33996     c7 0/subop/copy *Curr-block-depth 0/imm32
33997     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
33998     (flush _test-output-buffered-file)
33999 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34005     # check output
34006     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
34007     # . epilogue
34008     89/<- %esp 5/r32/ebp
34009     5d/pop-to-ebp
34010     c3/return
34011 
34012 test-compare-reg-with-reg:
34013     #   compare var1/ecx, var2/eax
34014     # =>
34015     #   39/compare %ecx 0/r32/eax
34016     #
34017     # . prologue
34018     55/push-ebp
34019     89/<- %ebp 4/r32/esp
34020     # setup
34021     (clear-stream _test-output-stream)
34022     (clear-stream $_test-output-buffered-file->buffer)
34023 $test-compare-reg-with-reg:initialize-type:
34024     # var type/ecx: (payload type-tree) = int
34025     68/push 0/imm32/right:null
34026     68/push 0/imm32/right:null
34027     68/push 0/imm32/left:unused
34028     68/push 1/imm32/value:int
34029     68/push 1/imm32/is-atom?:true
34030     68/push 0x11/imm32/alloc-id:fake:payload
34031     89/<- %ecx 4/r32/esp
34032 $test-compare-reg-with-reg:initialize-var1:
34033     # var var1/ecx: (payload var)
34034     68/push 0/imm32/register
34035     68/push 0/imm32/register
34036     68/push 0/imm32/no-stack-offset
34037     68/push 1/imm32/block-depth
34038     51/push-ecx
34039     68/push 0x11/imm32/alloc-id:fake
34040     68/push 0/imm32/name
34041     68/push 0/imm32/name
34042     68/push 0x11/imm32/alloc-id:fake:payload
34043     89/<- %ecx 4/r32/esp
34044 $test-compare-reg-with-reg:initialize-var1-name:
34045     # var1->name = "var1"
34046     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34047     (copy-array Heap "var1" %eax)
34048 $test-compare-reg-with-reg:initialize-var1-register:
34049     # var1->register = "ecx"
34050     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34051     (copy-array Heap "ecx" %eax)
34052 $test-compare-reg-with-reg:initialize-var2:
34053     # var var2/edx: (payload var)
34054     68/push 0/imm32/register
34055     68/push 0/imm32/register
34056     68/push 0/imm32/no-stack-offset
34057     68/push 1/imm32/block-depth
34058     ff 6/subop/push *(ecx+0x10)
34059     68/push 0x11/imm32/alloc-id:fake
34060     68/push 0/imm32/name
34061     68/push 0/imm32/name
34062     68/push 0x11/imm32/alloc-id:fake:payload
34063     89/<- %edx 4/r32/esp
34064 $test-compare-reg-with-reg:initialize-var2-name:
34065     # var2->name = "var2"
34066     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34067     (copy-array Heap "var2" %eax)
34068 $test-compare-reg-with-reg:initialize-var2-register:
34069     # var2->register = "eax"
34070     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34071     (copy-array Heap "eax" %eax)
34072 $test-compare-reg-with-reg:initialize-inouts:
34073     # var inouts/esi: (payload stmt-var) = [var2]
34074     68/push 0/imm32/is-deref:false
34075     68/push 0/imm32/next
34076     68/push 0/imm32/next
34077     52/push-edx/var2
34078     68/push 0x11/imm32/alloc-id:fake
34079     68/push 0x11/imm32/alloc-id:fake:payload
34080     89/<- %esi 4/r32/esp
34081     # inouts = [var1, var2]
34082     68/push 0/imm32/is-deref:false
34083     56/push-esi/next
34084     68/push 0x11/imm32/alloc-id:fake
34085     51/push-ecx/var1
34086     68/push 0x11/imm32/alloc-id:fake
34087     68/push 0x11/imm32/alloc-id:fake:payload
34088     89/<- %esi 4/r32/esp
34089 $test-compare-reg-with-reg:initialize-stmt:
34090     # var stmt/esi: (addr statement)
34091     68/push 0/imm32/next
34092     68/push 0/imm32/next
34093     68/push 0/imm32/outputs
34094     68/push 0/imm32/outputs
34095     56/push-esi/inouts
34096     68/push 0x11/imm32/alloc-id:fake
34097     68/push 0/imm32/operation
34098     68/push 0/imm32/operation
34099     68/push 1/imm32/tag:stmt1
34100     89/<- %esi 4/r32/esp
34101 $test-compare-reg-with-reg:initialize-stmt-operation:
34102     # stmt->operation = "compare"
34103     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34104     (copy-array Heap "compare" %eax)
34105     # convert
34106     c7 0/subop/copy *Curr-block-depth 0/imm32
34107     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34108     (flush _test-output-buffered-file)
34109 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34115     # check output
34116     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
34117     # . epilogue
34118     89/<- %esp 5/r32/ebp
34119     5d/pop-to-ebp
34120     c3/return
34121 
34122 test-compare-mem-with-reg:
34123     #   compare var1, var2/eax
34124     # =>
34125     #   39/compare *(ebp+___) 0/r32/eax
34126     #
34127     # . prologue
34128     55/push-ebp
34129     89/<- %ebp 4/r32/esp
34130     # setup
34131     (clear-stream _test-output-stream)
34132     (clear-stream $_test-output-buffered-file->buffer)
34133 $test-compare-mem-with-reg:initialize-type:
34134     # var type/ecx: (payload type-tree) = int
34135     68/push 0/imm32/right:null
34136     68/push 0/imm32/right:null
34137     68/push 0/imm32/left:unused
34138     68/push 1/imm32/value:int
34139     68/push 1/imm32/is-atom?:true
34140     68/push 0x11/imm32/alloc-id:fake:payload
34141     89/<- %ecx 4/r32/esp
34142 $test-compare-mem-with-reg:initialize-var1:
34143     # var var1/ecx: (payload var)
34144     68/push 0/imm32/register
34145     68/push 0/imm32/register
34146     68/push 8/imm32/stack-offset
34147     68/push 1/imm32/block-depth
34148     51/push-ecx
34149     68/push 0x11/imm32/alloc-id:fake
34150     68/push 0/imm32/name
34151     68/push 0/imm32/name
34152     68/push 0x11/imm32/alloc-id:fake:payload
34153     89/<- %ecx 4/r32/esp
34154 $test-compare-mem-with-reg:initialize-var1-name:
34155     # var1->name = "var1"
34156     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34157     (copy-array Heap "var1" %eax)
34158 $test-compare-mem-with-reg:initialize-var2:
34159     # var var2/edx: (payload var)
34160     68/push 0/imm32/register
34161     68/push 0/imm32/register
34162     68/push 0/imm32/no-stack-offset
34163     68/push 1/imm32/block-depth
34164     ff 6/subop/push *(ecx+0x10)
34165     68/push 0x11/imm32/alloc-id:fake
34166     68/push 0/imm32/name
34167     68/push 0/imm32/name
34168     68/push 0x11/imm32/alloc-id:fake:payload
34169     89/<- %edx 4/r32/esp
34170 $test-compare-mem-with-reg:initialize-var2-name:
34171     # var2->name = "var2"
34172     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34173     (copy-array Heap "var2" %eax)
34174 $test-compare-mem-with-reg:initialize-var2-register:
34175     # var2->register = "eax"
34176     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34177     (copy-array Heap "eax" %eax)
34178 $test-compare-mem-with-reg:initialize-inouts:
34179     # var inouts/esi: (payload stmt-var) = [var2]
34180     68/push 0/imm32/is-deref:false
34181     68/push 0/imm32/next
34182     68/push 0/imm32/next
34183     52/push-edx/var2
34184     68/push 0x11/imm32/alloc-id:fake
34185     68/push 0x11/imm32/alloc-id:fake:payload
34186     89/<- %esi 4/r32/esp
34187     # inouts = [var1, var2]
34188     68/push 0/imm32/is-deref:false
34189     56/push-esi/next
34190     68/push 0x11/imm32/alloc-id:fake
34191     51/push-ecx/var1
34192     68/push 0x11/imm32/alloc-id:fake
34193     68/push 0x11/imm32/alloc-id:fake:payload
34194     89/<- %esi 4/r32/esp
34195 $test-compare-mem-with-reg:initialize-stmt:
34196     # var stmt/esi: (addr statement)
34197     68/push 0/imm32/next
34198     68/push 0/imm32/next
34199     68/push 0/imm32/outputs
34200     68/push 0/imm32/outputs
34201     56/push-esi/inouts
34202     68/push 0x11/imm32/alloc-id:fake
34203     68/push 0/imm32/operation
34204     68/push 0/imm32/operation
34205     68/push 1/imm32/tag:stmt1
34206     89/<- %esi 4/r32/esp
34207 $test-compare-mem-with-reg:initialize-stmt-operation:
34208     # stmt->operation = "compare"
34209     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34210     (copy-array Heap "compare" %eax)
34211     # convert
34212     c7 0/subop/copy *Curr-block-depth 0/imm32
34213     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34214     (flush _test-output-buffered-file)
34215 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34221     # check output
34222     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
34223     # . epilogue
34224     89/<- %esp 5/r32/ebp
34225     5d/pop-to-ebp
34226     c3/return
34227 
34228 test-compare-reg-with-mem:
34229     #   compare var1/eax, var2
34230     # =>
34231     #   3b/compare<- *(ebp+___) 0/r32/eax
34232     #
34233     # . prologue
34234     55/push-ebp
34235     89/<- %ebp 4/r32/esp
34236     # setup
34237     (clear-stream _test-output-stream)
34238     (clear-stream $_test-output-buffered-file->buffer)
34239 $test-compare-reg-with-mem:initialize-type:
34240     # var type/ecx: (payload type-tree) = int
34241     68/push 0/imm32/right:null
34242     68/push 0/imm32/right:null
34243     68/push 0/imm32/left:unused
34244     68/push 1/imm32/value:int
34245     68/push 1/imm32/is-atom?:true
34246     68/push 0x11/imm32/alloc-id:fake:payload
34247     89/<- %ecx 4/r32/esp
34248 $test-compare-reg-with-mem:initialize-var1:
34249     # var var1/ecx: (payload var)
34250     68/push 0/imm32/register
34251     68/push 0/imm32/register
34252     68/push 0/imm32/no-stack-offset
34253     68/push 1/imm32/block-depth
34254     51/push-ecx
34255     68/push 0x11/imm32/alloc-id:fake
34256     68/push 0/imm32/name
34257     68/push 0/imm32/name
34258     68/push 0x11/imm32/alloc-id:fake:payload
34259     89/<- %ecx 4/r32/esp
34260 $test-compare-reg-with-mem:initialize-var1-name:
34261     # var1->name = "var1"
34262     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34263     (copy-array Heap "var1" %eax)
34264 $test-compare-reg-with-mem:initialize-var1-register:
34265     # var1->register = "eax"
34266     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34267     (copy-array Heap "eax" %eax)
34268 $test-compare-reg-with-mem:initialize-var2:
34269     # var var2/edx: (payload var)
34270     68/push 0/imm32/register
34271     68/push 0/imm32/register
34272     68/push 8/imm32/stack-offset
34273     68/push 1/imm32/block-depth
34274     ff 6/subop/push *(ecx+0x10)
34275     68/push 0x11/imm32/alloc-id:fake
34276     68/push 0/imm32/name
34277     68/push 0/imm32/name
34278     68/push 0x11/imm32/alloc-id:fake:payload
34279     89/<- %edx 4/r32/esp
34280 $test-compare-reg-with-mem:initialize-var2-name:
34281     # var2->name = "var2"
34282     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34283     (copy-array Heap "var2" %eax)
34284 $test-compare-reg-with-mem:initialize-inouts:
34285     # var inouts/esi: (payload stmt-var) = [var2]
34286     68/push 0/imm32/is-deref:false
34287     68/push 0/imm32/next
34288     68/push 0/imm32/next
34289     52/push-edx/var2
34290     68/push 0x11/imm32/alloc-id:fake
34291     68/push 0x11/imm32/alloc-id:fake:payload
34292     89/<- %esi 4/r32/esp
34293     # inouts = [var1, var2]
34294     68/push 0/imm32/is-deref:false
34295     56/push-esi/next
34296     68/push 0x11/imm32/alloc-id:fake
34297     51/push-ecx/var1
34298     68/push 0x11/imm32/alloc-id:fake
34299     68/push 0x11/imm32/alloc-id:fake:payload
34300     89/<- %esi 4/r32/esp
34301 $test-compare-reg-with-mem:initialize-stmt:
34302     # var stmt/esi: (addr statement)
34303     68/push 0/imm32/next
34304     68/push 0/imm32/next
34305     68/push 0/imm32/outputs
34306     68/push 0/imm32/outputs
34307     56/push-esi/inouts
34308     68/push 0x11/imm32/alloc-id:fake
34309     68/push 0/imm32/operation
34310     68/push 0/imm32/operation
34311     68/push 1/imm32/tag:stmt1
34312     89/<- %esi 4/r32/esp
34313 $test-compare-reg-with-mem:initialize-stmt-operation:
34314     # stmt->operation = "compare"
34315     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34316     (copy-array Heap "compare" %eax)
34317     # convert
34318     c7 0/subop/copy *Curr-block-depth 0/imm32
34319     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34320     (flush _test-output-buffered-file)
34321 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34327     # check output
34328     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
34329     # . epilogue
34330     89/<- %esp 5/r32/ebp
34331     5d/pop-to-ebp
34332     c3/return
34333 
34334 test-compare-mem-with-literal:
34335     #   compare var1, 0x34
34336     # =>
34337     #   81 7/subop/compare *(ebp+___) 0x34/imm32
34338     #
34339     # . prologue
34340     55/push-ebp
34341     89/<- %ebp 4/r32/esp
34342     # setup
34343     (clear-stream _test-output-stream)
34344     (clear-stream $_test-output-buffered-file->buffer)
34345 $test-compare-mem-with-literal:initialize-type:
34346     # var type/ecx: (payload type-tree) = int
34347     68/push 0/imm32/right:null
34348     68/push 0/imm32/right:null
34349     68/push 0/imm32/left:unused
34350     68/push 1/imm32/value:int
34351     68/push 1/imm32/is-atom?:true
34352     68/push 0x11/imm32/alloc-id:fake:payload
34353     89/<- %ecx 4/r32/esp
34354 $test-compare-mem-with-literal:initialize-var1:
34355     # var var1/ecx: (payload var)
34356     68/push 0/imm32/register
34357     68/push 0/imm32/register
34358     68/push 8/imm32/stack-offset
34359     68/push 1/imm32/block-depth
34360     51/push-ecx
34361     68/push 0x11/imm32/alloc-id:fake
34362     68/push 0/imm32/name
34363     68/push 0/imm32/name
34364     68/push 0x11/imm32/alloc-id:fake:payload
34365     89/<- %ecx 4/r32/esp
34366 $test-compare-mem-with-literal:initialize-var1-name:
34367     # var1->name = "var1"
34368     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34369     (copy-array Heap "var1" %eax)
34370 $test-compare-mem-with-literal:initialize-literal-type:
34371     # var type/edx: (payload type-tree) = literal
34372     68/push 0/imm32/right:null
34373     68/push 0/imm32/right:null
34374     68/push 0/imm32/left:unused
34375     68/push 0/imm32/value:literal
34376     68/push 1/imm32/is-atom?:true
34377     68/push 0x11/imm32/alloc-id:fake:payload
34378     89/<- %edx 4/r32/esp
34379 $test-compare-mem-with-literal:initialize-literal:
34380     # var l/edx: (payload var)
34381     68/push 0/imm32/register
34382     68/push 0/imm32/register
34383     68/push 0/imm32/no-stack-offset
34384     68/push 1/imm32/block-depth
34385     52/push-edx
34386     68/push 0x11/imm32/alloc-id:fake
34387     68/push 0/imm32/name
34388     68/push 0/imm32/name
34389     68/push 0x11/imm32/alloc-id:fake:payload
34390     89/<- %edx 4/r32/esp
34391 $test-compare-mem-with-literal:initialize-literal-value:
34392     # l->name = "0x34"
34393     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34394     (copy-array Heap "0x34" %eax)
34395 $test-compare-mem-with-literal:initialize-inouts:
34396     # var inouts/esi: (payload stmt-var) = [l]
34397     68/push 0/imm32/is-deref:false
34398     68/push 0/imm32/next
34399     68/push 0/imm32/next
34400     52/push-edx/l
34401     68/push 0x11/imm32/alloc-id:fake
34402     68/push 0x11/imm32/alloc-id:fake:payload
34403     89/<- %esi 4/r32/esp
34404     # var inouts = (handle stmt-var) = [var1, var2]
34405     68/push 0/imm32/is-deref:false
34406     56/push-esi/next
34407     68/push 0x11/imm32/alloc-id:fake
34408     51/push-ecx/var1
34409     68/push 0x11/imm32/alloc-id:fake
34410     68/push 0x11/imm32/alloc-id:fake:payload
34411     89/<- %esi 4/r32/esp
34412 $test-compare-mem-with-literal:initialize-stmt:
34413     # var stmt/esi: (addr statement)
34414     68/push 0/imm32/next
34415     68/push 0/imm32/next
34416     68/push 0/imm32/outputs
34417     68/push 0/imm32/outputs
34418     56/push-esi/inouts
34419     68/push 0x11/imm32/alloc-id:fake
34420     68/push 0/imm32/operation
34421     68/push 0/imm32/operation
34422     68/push 1/imm32/tag:stmt1
34423     89/<- %esi 4/r32/esp
34424 $test-compare-mem-with-literal:initialize-stmt-operation:
34425     # stmt->operation = "compare"
34426     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34427     (copy-array Heap "compare" %eax)
34428     # convert
34429     c7 0/subop/copy *Curr-block-depth 0/imm32
34430     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34431     (flush _test-output-buffered-file)
34432 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34438     # check output
34439     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
34440     # . epilogue
34441     89/<- %esp 5/r32/ebp
34442     5d/pop-to-ebp
34443     c3/return
34444 
34445 test-compare-eax-with-literal:
34446     #   compare var1/eax 0x34
34447     # =>
34448     #   3d/compare-eax-with 0x34/imm32
34449     #
34450     # . prologue
34451     55/push-ebp
34452     89/<- %ebp 4/r32/esp
34453     # setup
34454     (clear-stream _test-output-stream)
34455     (clear-stream $_test-output-buffered-file->buffer)
34456 $test-compare-eax-with-literal:initialize-type:
34457     # var type/ecx: (payload type-tree) = int
34458     68/push 0/imm32/right:null
34459     68/push 0/imm32/right:null
34460     68/push 0/imm32/left:unused
34461     68/push 1/imm32/value:int
34462     68/push 1/imm32/is-atom?:true
34463     68/push 0x11/imm32/alloc-id:fake:payload
34464     89/<- %ecx 4/r32/esp
34465 $test-compare-eax-with-literal:initialize-var1:
34466     # var var1/ecx: (payload var)
34467     68/push 0/imm32/register
34468     68/push 0/imm32/register
34469     68/push 0/imm32/no-stack-offset
34470     68/push 1/imm32/block-depth
34471     51/push-ecx
34472     68/push 0x11/imm32/alloc-id:fake
34473     68/push 0/imm32/name
34474     68/push 0/imm32/name
34475     68/push 0x11/imm32/alloc-id:fake:payload
34476     89/<- %ecx 4/r32/esp
34477 $test-compare-eax-with-literal:initialize-var1-name:
34478     # var1->name = "var1"
34479     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34480     (copy-array Heap "var1" %eax)
34481 $test-compare-eax-with-literal:initialize-var1-register:
34482     # v->register = "eax"
34483     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34484     (copy-array Heap "eax" %eax)
34485 $test-compare-eax-with-literal:initialize-literal-type:
34486     # var type/edx: (payload type-tree) = literal
34487     68/push 0/imm32/right:null
34488     68/push 0/imm32/right:null
34489     68/push 0/imm32/left:unused
34490     68/push 0/imm32/value:literal
34491     68/push 1/imm32/is-atom?:true
34492     68/push 0x11/imm32/alloc-id:fake:payload
34493     89/<- %edx 4/r32/esp
34494 $test-compare-eax-with-literal:initialize-literal:
34495     # var l/edx: (payload var)
34496     68/push 0/imm32/register
34497     68/push 0/imm32/register
34498     68/push 0/imm32/no-stack-offset
34499     68/push 1/imm32/block-depth
34500     52/push-edx
34501     68/push 0x11/imm32/alloc-id:fake
34502     68/push 0/imm32/name
34503     68/push 0/imm32/name
34504     68/push 0x11/imm32/alloc-id:fake:payload
34505     89/<- %edx 4/r32/esp
34506 $test-compare-eax-with-literal:initialize-literal-value:
34507     # l->name = "0x34"
34508     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34509     (copy-array Heap "0x34" %eax)
34510 $test-compare-eax-with-literal:initialize-inouts:
34511     # var inouts/esi: (payload stmt-var) = [l]
34512     68/push 0/imm32/is-deref:false
34513     68/push 0/imm32/next
34514     68/push 0/imm32/next
34515     52/push-edx/l
34516     68/push 0x11/imm32/alloc-id:fake
34517     68/push 0x11/imm32/alloc-id:fake:payload
34518     89/<- %esi 4/r32/esp
34519     # var inouts = (handle stmt-var) = [var1, var2]
34520     68/push 0/imm32/is-deref:false
34521     56/push-esi/next
34522     68/push 0x11/imm32/alloc-id:fake
34523     51/push-ecx/var1
34524     68/push 0x11/imm32/alloc-id:fake
34525     68/push 0x11/imm32/alloc-id:fake:payload
34526     89/<- %esi 4/r32/esp
34527 $test-compare-eax-with-literal:initialize-stmt:
34528     # var stmt/esi: (addr statement)
34529     68/push 0/imm32/next
34530     68/push 0/imm32/next
34531     68/push 0/imm32/outputs
34532     68/push 0/imm32/outputs
34533     56/push-esi/inouts
34534     68/push 0x11/imm32/alloc-id:fake
34535     68/push 0/imm32/operation
34536     68/push 0/imm32/operation
34537     68/push 1/imm32/tag:stmt1
34538     89/<- %esi 4/r32/esp
34539 $test-compare-eax-with-literal:initialize-stmt-operation:
34540     # stmt->operation = "compare"
34541     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34542     (copy-array Heap "compare" %eax)
34543     # convert
34544     c7 0/subop/copy *Curr-block-depth 0/imm32
34545     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34546     (flush _test-output-buffered-file)
34547 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34553     # check output
34554     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
34555     # . epilogue
34556     89/<- %esp 5/r32/ebp
34557     5d/pop-to-ebp
34558     c3/return
34559 
34560 test-compare-reg-with-literal:
34561     #   compare var1/ecx 0x34
34562     # =>
34563     #   81 7/subop/compare %ecx 0x34/imm32
34564     #
34565     # . prologue
34566     55/push-ebp
34567     89/<- %ebp 4/r32/esp
34568     # setup
34569     (clear-stream _test-output-stream)
34570     (clear-stream $_test-output-buffered-file->buffer)
34571 $test-compare-reg-with-literal:initialize-type:
34572     # var type/ecx: (payload type-tree) = int
34573     68/push 0/imm32/right:null
34574     68/push 0/imm32/right:null
34575     68/push 0/imm32/left:unused
34576     68/push 1/imm32/value:int
34577     68/push 1/imm32/is-atom?:true
34578     68/push 0x11/imm32/alloc-id:fake:payload
34579     89/<- %ecx 4/r32/esp
34580 $test-compare-reg-with-literal:initialize-var1:
34581     # var var1/ecx: (payload var)
34582     68/push 0/imm32/register
34583     68/push 0/imm32/register
34584     68/push 0/imm32/no-stack-offset
34585     68/push 1/imm32/block-depth
34586     51/push-ecx
34587     68/push 0x11/imm32/alloc-id:fake
34588     68/push 0/imm32/name
34589     68/push 0/imm32/name
34590     68/push 0x11/imm32/alloc-id:fake:payload
34591     89/<- %ecx 4/r32/esp
34592 $test-compare-reg-with-literal:initialize-var1-name:
34593     # var1->name = "var1"
34594     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34595     (copy-array Heap "var1" %eax)
34596 $test-compare-reg-with-literal:initialize-var1-register:
34597     # v->register = "ecx"
34598     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34599     (copy-array Heap "ecx" %eax)
34600 $test-compare-reg-with-literal:initialize-literal-type:
34601     # var type/edx: (payload type-tree) = literal
34602     68/push 0/imm32/right:null
34603     68/push 0/imm32/right:null
34604     68/push 0/imm32/left:unused
34605     68/push 0/imm32/value:literal
34606     68/push 1/imm32/is-atom?:true
34607     68/push 0x11/imm32/alloc-id:fake:payload
34608     89/<- %edx 4/r32/esp
34609 $test-compare-reg-with-literal:initialize-literal:
34610     # var l/edx: (payload var)
34611     68/push 0/imm32/register
34612     68/push 0/imm32/register
34613     68/push 0/imm32/no-stack-offset
34614     68/push 1/imm32/block-depth
34615     52/push-edx
34616     68/push 0x11/imm32/alloc-id:fake
34617     68/push 0/imm32/name
34618     68/push 0/imm32/name
34619     68/push 0x11/imm32/alloc-id:fake:payload
34620     89/<- %edx 4/r32/esp
34621 $test-compare-reg-with-literal:initialize-literal-value:
34622     # l->name = "0x34"
34623     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34624     (copy-array Heap "0x34" %eax)
34625 $test-compare-reg-with-literal:initialize-inouts:
34626     # var inouts/esi: (payload stmt-var) = [l]
34627     68/push 0/imm32/is-deref:false
34628     68/push 0/imm32/next
34629     68/push 0/imm32/next
34630     52/push-edx/l
34631     68/push 0x11/imm32/alloc-id:fake
34632     68/push 0x11/imm32/alloc-id:fake:payload
34633     89/<- %esi 4/r32/esp
34634     # var inouts = (handle stmt-var) = [var1, var2]
34635     68/push 0/imm32/is-deref:false
34636     56/push-esi/next
34637     68/push 0x11/imm32/alloc-id:fake
34638     51/push-ecx/var1
34639     68/push 0x11/imm32/alloc-id:fake
34640     68/push 0x11/imm32/alloc-id:fake:payload
34641     89/<- %esi 4/r32/esp
34642 $test-compare-reg-with-literal:initialize-stmt:
34643     # var stmt/esi: (addr statement)
34644     68/push 0/imm32/next
34645     68/push 0/imm32/next
34646     68/push 0/imm32/outputs
34647     68/push 0/imm32/outputs
34648     56/push-esi/inouts
34649     68/push 0x11/imm32/alloc-id:fake
34650     68/push 0/imm32/operation
34651     68/push 0/imm32/operation
34652     68/push 1/imm32/tag:stmt1
34653     89/<- %esi 4/r32/esp
34654 $test-compare-reg-with-literal:initialize-stmt-operation:
34655     # stmt->operation = "compare"
34656     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34657     (copy-array Heap "compare" %eax)
34658     # convert
34659     c7 0/subop/copy *Curr-block-depth 0/imm32
34660     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34661     (flush _test-output-buffered-file)
34662 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34668     # check output
34669     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
34670     # . epilogue
34671     89/<- %esp 5/r32/ebp
34672     5d/pop-to-ebp
34673     c3/return
34674 
34675 test-emit-subx-stmt-function-call:
34676     # Call a function on a variable on the stack.
34677     #   f foo
34678     # =>
34679     #   (f *(ebp-8))
34680     # (Changing the function name supports overloading in general, but here it
34681     # just serves to help disambiguate things.)
34682     #
34683     # There's a variable on the var stack as follows:
34684     #   name: 'foo'
34685     #   type: int
34686     #   stack-offset: -8
34687     #
34688     # There's nothing in primitives.
34689     #
34690     # We don't perform any checking here on the type of 'f'.
34691     #
34692     # . prologue
34693     55/push-ebp
34694     89/<- %ebp 4/r32/esp
34695     # setup
34696     (clear-stream _test-output-stream)
34697     (clear-stream $_test-output-buffered-file->buffer)
34698 $test-emit-subx-function-call:initialize-type:
34699     # var type/ecx: (payload type-tree) = int
34700     68/push 0/imm32/right:null
34701     68/push 0/imm32/right:null
34702     68/push 0/imm32/left:unused
34703     68/push 1/imm32/value:int
34704     68/push 1/imm32/is-atom?:true
34705     68/push 0x11/imm32/alloc-id:fake:payload
34706     89/<- %ecx 4/r32/esp
34707 $test-emit-subx-function-call:initialize-var:
34708     # var var-foo/ecx: (payload var) = var(type)
34709     68/push 0/imm32/no-register
34710     68/push 0/imm32/no-register
34711     68/push -8/imm32/stack-offset
34712     68/push 1/imm32/block-depth
34713     51/push-ecx/type
34714     68/push 0x11/imm32/alloc-id:fake
34715     68/push 0/imm32/name
34716     68/push 0/imm32/name
34717     68/push 0x11/imm32/alloc-id:fake:payload
34718     89/<- %ecx 4/r32/esp
34719 $test-emit-subx-function-call:initialize-var-name:
34720     # var-foo->name = "foo"
34721     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34722     (copy-array Heap "foo" %eax)
34723 $test-emit-subx-function-call:initialize-stmt-var:
34724     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
34725     68/push 0/imm32/is-deref:false
34726     68/push 0/imm32/next
34727     68/push 0/imm32/next
34728     51/push-ecx/var-foo
34729     68/push 0x11/imm32/alloc-id:fake
34730     68/push 0x11/imm32/alloc-id:fake:payload
34731     89/<- %ebx 4/r32/esp
34732 $test-emit-subx-function-call:initialize-stmt:
34733     # var stmt/esi: (addr statement)
34734     68/push 0/imm32/no-outputs
34735     68/push 0/imm32/no-outputs
34736     53/push-ebx/inouts
34737     68/push 0x11/imm32/alloc-id:fake
34738     68/push 0/imm32/operation
34739     68/push 0/imm32/operation
34740     68/push 1/imm32/tag
34741     89/<- %esi 4/r32/esp
34742 $test-emit-subx-function-call:initialize-stmt-operation:
34743     # stmt->operation = "f"
34744     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34745     (copy-array Heap "f" %eax)
34746     # convert
34747     c7 0/subop/copy *Curr-block-depth 0/imm32
34748     (emit-subx-stmt _test-output-buffered-file %esi 0 Stderr 0)
34749     (flush _test-output-buffered-file)
34750 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34756     # check output
34757     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
34758     # . epilogue
34759     89/<- %esp 5/r32/ebp
34760     5d/pop-to-ebp
34761     c3/return
34762 
34763 test-emit-subx-stmt-function-call-with-literal-arg:
34764     # Call a function on a literal.
34765     #   f 0x34
34766     # =>
34767     #   (f2 0x34)
34768     #
34769     # . prologue
34770     55/push-ebp
34771     89/<- %ebp 4/r32/esp
34772     # setup
34773     (clear-stream _test-output-stream)
34774     (clear-stream $_test-output-buffered-file->buffer)
34775 $test-emit-subx-function-call-with-literal-arg:initialize-type:
34776     # var type/ecx: (payload type-tree) = int
34777     68/push 0/imm32/right:null
34778     68/push 0/imm32/right:null
34779     68/push 0/imm32/left:unused
34780     68/push 0/imm32/value:literal
34781     68/push 1/imm32/is-atom?:true
34782     68/push 0x11/imm32/alloc-id:fake:payload
34783     89/<- %ecx 4/r32/esp
34784 $test-emit-subx-function-call-with-literal-arg:initialize-var:
34785     # var var-foo/ecx: (payload var) = var(lit)
34786     68/push 0/imm32/no-register
34787     68/push 0/imm32/no-register
34788     68/push 0/imm32/no-stack-offset
34789     68/push 1/imm32/block-depth
34790     51/push-ecx/type
34791     68/push 0x11/imm32/alloc-id:fake
34792     68/push 0/imm32/name
34793     68/push 0/imm32/name
34794     68/push 0x11/imm32/alloc-id:fake:payload
34795     89/<- %ecx 4/r32/esp
34796 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
34797     # var-foo->name = "0x34"
34798     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34799     (copy-array Heap "0x34" %eax)
34800 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
34801     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
34802     68/push 0/imm32/is-deref:false
34803     68/push 0/imm32/next
34804     68/push 0/imm32/next
34805     51/push-ecx/var-foo
34806     68/push 0x11/imm32/alloc-id:fake
34807     68/push 0x11/imm32/alloc-id:fake:payload
34808     89/<- %ebx 4/r32/esp
34809 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
34810     # var stmt/esi: (addr statement)
34811     68/push 0/imm32/no-outputs
34812     68/push 0/imm32/no-outputs
34813     53/push-ebx/inouts
34814     68/push 0x11/imm32/alloc-id:fake
34815     68/push 0/imm32/operation
34816     68/push 0/imm32/operation
34817     68/push 1/imm32/tag
34818     89/<- %esi 4/r32/esp
34819 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
34820     # stmt->operation = "f"
34821     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34822     (copy-array Heap "f" %eax)
34823     # convert
34824     c7 0/subop/copy *Curr-block-depth 0/imm32
34825     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx Stderr 0)
34826     (flush _test-output-buffered-file)
34827 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34833     # check output
34834     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
34835     # . epilogue
34836     89/<- %esp 5/r32/ebp
34837     5d/pop-to-ebp
34838     c3/return
34839 
34840 emit-indent:  # out: (addr buffered-file), n: int
34841     # . prologue
34842     55/push-ebp
34843     89/<- %ebp 4/r32/esp
34844     # . save registers
34845     50/push-eax
34846     # var i/eax: int = n
34847     8b/-> *(ebp+0xc) 0/r32/eax
34848     {
34849       # if (i <= 0) break
34850       3d/compare-eax-with 0/imm32
34851       7e/jump-if-<= break/disp8
34852       (write-buffered *(ebp+8) "  ")
34853       48/decrement-eax
34854       eb/jump loop/disp8
34855     }
34856 $emit-indent:end:
34857     # . restore registers
34858     58/pop-to-eax
34859     # . epilogue
34860     89/<- %esp 5/r32/ebp
34861     5d/pop-to-ebp
34862     c3/return
34863 
34864 emit-subx-prologue:  # out: (addr buffered-file)
34865     # . prologue
34866     55/push-ebp
34867     89/<- %ebp 4/r32/esp
34868     #
34869     (write-buffered *(ebp+8) "  # . prologue\n")
34870     (write-buffered *(ebp+8) "  55/push-ebp\n")
34871     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
34872 $emit-subx-prologue:end:
34873     # . epilogue
34874     89/<- %esp 5/r32/ebp
34875     5d/pop-to-ebp
34876     c3/return
34877 
34878 emit-subx-epilogue:  # out: (addr buffered-file)
34879     # . prologue
34880     55/push-ebp
34881     89/<- %ebp 4/r32/esp
34882     #
34883     (write-buffered *(ebp+8) "  # . epilogue\n")
34884     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
34885     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
34886     (write-buffered *(ebp+8) "  c3/return\n")
34887 $emit-subx-epilogue:end:
34888     # . epilogue
34889     89/<- %esp 5/r32/ebp
34890     5d/pop-to-ebp
34891     c3/return